feat(O): Android 首页近期动态实时刷新
- 新增 ActivityEventBus(进程级静态回调, 主线程派发) - PlatformServiceManager/DeviceControlActivity/TuyaSdkService 在动态落库成功后 notify - HomeFragment 注册监听并 400ms 防抖重载近期动态, onResume/onHiddenChanged 兜底刷新
This commit is contained in:
parent
4c8aa5459d
commit
da28d3b543
@ -145,6 +145,8 @@ public class PlatformServiceManager {
|
|||||||
@Override
|
@Override
|
||||||
public void onResponse(retrofit2.Call<Result<Void>> call,
|
public void onResponse(retrofit2.Call<Result<Void>> call,
|
||||||
retrofit2.Response<Result<Void>> response) {
|
retrofit2.Response<Result<Void>> response) {
|
||||||
|
// 动态已落库,通知首页「近期动态」实时刷新
|
||||||
|
com.xhai.iot.util.ActivityEventBus.notifyChanged(device.getDeviceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -95,6 +95,8 @@ public class TuyaSdkService {
|
|||||||
@Override
|
@Override
|
||||||
public void onResponse(retrofit2.Call<com.xhai.iot.model.Result<Integer>> call,
|
public void onResponse(retrofit2.Call<com.xhai.iot.model.Result<Integer>> call,
|
||||||
retrofit2.Response<com.xhai.iot.model.Result<Integer>> response) {
|
retrofit2.Response<com.xhai.iot.model.Result<Integer>> response) {
|
||||||
|
// 后端已记录 DP 变化动态(source=panel),通知首页刷新近期动态
|
||||||
|
com.xhai.iot.util.ActivityEventBus.notifyChanged(devId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1122,6 +1122,8 @@ public class DeviceControlActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void onResponse(retrofit2.Call<com.xhai.iot.model.Result<Void>> call,
|
public void onResponse(retrofit2.Call<com.xhai.iot.model.Result<Void>> call,
|
||||||
retrofit2.Response<com.xhai.iot.model.Result<Void>> response) {
|
retrofit2.Response<com.xhai.iot.model.Result<Void>> response) {
|
||||||
|
// 动态已落库,通知首页「近期动态」实时刷新
|
||||||
|
com.xhai.iot.util.ActivityEventBus.notifyChanged(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import com.xhai.iot.model.Result;
|
|||||||
import com.xhai.iot.model.TuyaDevice;
|
import com.xhai.iot.model.TuyaDevice;
|
||||||
import com.xhai.iot.service.TuyaSdkService;
|
import com.xhai.iot.service.TuyaSdkService;
|
||||||
import com.xhai.iot.ui.adapter.HomeDeviceAdapter;
|
import com.xhai.iot.ui.adapter.HomeDeviceAdapter;
|
||||||
|
import com.xhai.iot.util.ActivityEventBus;
|
||||||
import com.xhai.iot.util.SessionManager;
|
import com.xhai.iot.util.SessionManager;
|
||||||
import com.xhai.iot.util.ThemeManager;
|
import com.xhai.iot.util.ThemeManager;
|
||||||
import com.thingclips.smart.sdk.api.IDevListener;
|
import com.thingclips.smart.sdk.api.IDevListener;
|
||||||
@ -93,6 +94,8 @@ public class HomeFragment extends Fragment {
|
|||||||
loadRecentActivities();
|
loadRecentActivities();
|
||||||
// 注册设备状态回调,物理开关/远程状态变化时实时刷新列表
|
// 注册设备状态回调,物理开关/远程状态变化时实时刷新列表
|
||||||
TuyaSdkService.registerStatusCallback(deviceStatusCallback);
|
TuyaSdkService.registerStatusCallback(deviceStatusCallback);
|
||||||
|
// 注册动态事件回调:任意控制落库成功后,首页「近期动态」立即刷新
|
||||||
|
ActivityEventBus.register(activityEventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -100,6 +103,11 @@ public class HomeFragment extends Fragment {
|
|||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
unregisterAllTuyaListeners();
|
unregisterAllTuyaListeners();
|
||||||
TuyaSdkService.unregisterStatusCallback(deviceStatusCallback);
|
TuyaSdkService.unregisterStatusCallback(deviceStatusCallback);
|
||||||
|
ActivityEventBus.unregister(activityEventListener);
|
||||||
|
if (activityRefreshTask != null) {
|
||||||
|
activityRefreshHandler.removeCallbacks(activityRefreshTask);
|
||||||
|
activityRefreshTask = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -112,6 +120,8 @@ public class HomeFragment extends Fragment {
|
|||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
loadDevicesFromBackend();
|
loadDevicesFromBackend();
|
||||||
|
// 兜底:页面回到前台时同步一次近期动态(覆盖进程内事件丢失的情况)
|
||||||
|
scheduleActivityRefresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,9 +132,35 @@ public class HomeFragment extends Fragment {
|
|||||||
if (!hidden && adapter != null && isAdded()) {
|
if (!hidden && adapter != null && isAdded()) {
|
||||||
adapter.setAccentColor(ThemeManager.getInstance(requireContext()).accent().value);
|
adapter.setAccentColor(ThemeManager.getInstance(requireContext()).accent().value);
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
|
// 兜底:切回首页时同步一次近期动态
|
||||||
|
scheduleActivityRefresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 近期动态实时刷新 ====================
|
||||||
|
|
||||||
|
/** 动态事件回调:控制落库成功后触发「近期动态」重载 */
|
||||||
|
private final ActivityEventBus.Listener activityEventListener = deviceId -> {
|
||||||
|
if (!isAdded()) return;
|
||||||
|
android.util.Log.i("HomeFragment", "动态事件触发刷新: deviceId=" + deviceId);
|
||||||
|
scheduleActivityRefresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 动态刷新防抖时间(合并短时间内连续触发) */
|
||||||
|
private static final long ACTIVITY_REFRESH_DEBOUNCE_MS = 400L;
|
||||||
|
private final android.os.Handler activityRefreshHandler =
|
||||||
|
new android.os.Handler(android.os.Looper.getMainLooper());
|
||||||
|
private Runnable activityRefreshTask;
|
||||||
|
|
||||||
|
/** 防抖刷新近期动态 */
|
||||||
|
private void scheduleActivityRefresh() {
|
||||||
|
if (activityRefreshTask != null) {
|
||||||
|
activityRefreshHandler.removeCallbacks(activityRefreshTask);
|
||||||
|
}
|
||||||
|
activityRefreshTask = this::loadRecentActivities;
|
||||||
|
activityRefreshHandler.postDelayed(activityRefreshTask, ACTIVITY_REFRESH_DEBOUNCE_MS);
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== 刷新节流(避免高频全量重绑导致界面闪动) ====================
|
// ==================== 刷新节流(避免高频全量重绑导致界面闪动) ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,69 @@
|
|||||||
|
package com.xhai.iot.util;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备动态(操控记录)事件总线。
|
||||||
|
*
|
||||||
|
* <p>首页「近期动态」是后端 device_activity_log 的快照,控制动作本身走涂鸦 SDK 直连、
|
||||||
|
* 不经后端,所以必须由客户端在动态<b>落库成功</b>之后主动通知 UI 刷新,否则首页列表
|
||||||
|
* 一直停留在进入页面那一刻的静态数据。</p>
|
||||||
|
*
|
||||||
|
* <p>实现方式与 {@code TuyaSdkService} 的状态回调保持一致:进程级静态回调列表,
|
||||||
|
* 页面注册/注销,事件在主线程派发。</p>
|
||||||
|
*/
|
||||||
|
public final class ActivityEventBus {
|
||||||
|
|
||||||
|
/** 动态变更监听 */
|
||||||
|
public interface Listener {
|
||||||
|
/**
|
||||||
|
* @param deviceId 发生动态的设备ID,可能为 null(表示全局刷新)
|
||||||
|
*/
|
||||||
|
void onActivityChanged(String deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final List<Listener> listeners = new ArrayList<>();
|
||||||
|
private static final Handler MAIN = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
|
private ActivityEventBus() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 注册监听 */
|
||||||
|
public static void register(Listener listener) {
|
||||||
|
if (listener == null) return;
|
||||||
|
synchronized (listeners) {
|
||||||
|
if (!listeners.contains(listener)) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 注销监听 */
|
||||||
|
public static void unregister(Listener listener) {
|
||||||
|
if (listener == null) return;
|
||||||
|
synchronized (listeners) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 通知所有监听:设备动态已新增(落库成功后才调用) */
|
||||||
|
public static void notifyChanged(String deviceId) {
|
||||||
|
final List<Listener> snapshot;
|
||||||
|
synchronized (listeners) {
|
||||||
|
if (listeners.isEmpty()) return;
|
||||||
|
snapshot = new ArrayList<>(listeners);
|
||||||
|
}
|
||||||
|
MAIN.post(() -> {
|
||||||
|
for (Listener l : snapshot) {
|
||||||
|
try {
|
||||||
|
l.onActivityChanged(deviceId);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user