From da28d3b543cd450ab6e8258c027f1a2a1aa2e7f2 Mon Sep 17 00:00:00 2001 From: 2995840376 <2995840376@xiaomi.com> Date: Wed, 28 Oct 2026 10:48:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(O):=20Android=20=E9=A6=96=E9=A1=B5?= =?UTF-8?q?=E8=BF=91=E6=9C=9F=E5=8A=A8=E6=80=81=E5=AE=9E=E6=97=B6=E5=88=B7?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 ActivityEventBus(进程级静态回调, 主线程派发) - PlatformServiceManager/DeviceControlActivity/TuyaSdkService 在动态落库成功后 notify - HomeFragment 注册监听并 400ms 防抖重载近期动态, onResume/onHiddenChanged 兜底刷新 --- .../iot/service/PlatformServiceManager.java | 2 + .../com/xhai/iot/service/TuyaSdkService.java | 2 + .../xhai/iot/ui/DeviceControlActivity.java | 2 + .../java/com/xhai/iot/ui/HomeFragment.java | 36 ++++++++++ .../com/xhai/iot/util/ActivityEventBus.java | 69 +++++++++++++++++++ 5 files changed, 111 insertions(+) create mode 100644 Android/app/src/main/java/com/xhai/iot/util/ActivityEventBus.java diff --git a/Android/app/src/main/java/com/xhai/iot/service/PlatformServiceManager.java b/Android/app/src/main/java/com/xhai/iot/service/PlatformServiceManager.java index dbdcc33..fbdd0b9 100644 --- a/Android/app/src/main/java/com/xhai/iot/service/PlatformServiceManager.java +++ b/Android/app/src/main/java/com/xhai/iot/service/PlatformServiceManager.java @@ -145,6 +145,8 @@ public class PlatformServiceManager { @Override public void onResponse(retrofit2.Call> call, retrofit2.Response> response) { + // 动态已落库,通知首页「近期动态」实时刷新 + com.xhai.iot.util.ActivityEventBus.notifyChanged(device.getDeviceId()); } @Override diff --git a/Android/app/src/main/java/com/xhai/iot/service/TuyaSdkService.java b/Android/app/src/main/java/com/xhai/iot/service/TuyaSdkService.java index af9b26b..b9e3b39 100644 --- a/Android/app/src/main/java/com/xhai/iot/service/TuyaSdkService.java +++ b/Android/app/src/main/java/com/xhai/iot/service/TuyaSdkService.java @@ -95,6 +95,8 @@ public class TuyaSdkService { @Override public void onResponse(retrofit2.Call> call, retrofit2.Response> response) { + // 后端已记录 DP 变化动态(source=panel),通知首页刷新近期动态 + com.xhai.iot.util.ActivityEventBus.notifyChanged(devId); } @Override diff --git a/Android/app/src/main/java/com/xhai/iot/ui/DeviceControlActivity.java b/Android/app/src/main/java/com/xhai/iot/ui/DeviceControlActivity.java index 9675268..35c8480 100644 --- a/Android/app/src/main/java/com/xhai/iot/ui/DeviceControlActivity.java +++ b/Android/app/src/main/java/com/xhai/iot/ui/DeviceControlActivity.java @@ -1122,6 +1122,8 @@ public class DeviceControlActivity extends AppCompatActivity { @Override public void onResponse(retrofit2.Call> call, retrofit2.Response> response) { + // 动态已落库,通知首页「近期动态」实时刷新 + com.xhai.iot.util.ActivityEventBus.notifyChanged(deviceId); } @Override diff --git a/Android/app/src/main/java/com/xhai/iot/ui/HomeFragment.java b/Android/app/src/main/java/com/xhai/iot/ui/HomeFragment.java index e9b7af9..bb21373 100644 --- a/Android/app/src/main/java/com/xhai/iot/ui/HomeFragment.java +++ b/Android/app/src/main/java/com/xhai/iot/ui/HomeFragment.java @@ -28,6 +28,7 @@ import com.xhai.iot.model.Result; import com.xhai.iot.model.TuyaDevice; import com.xhai.iot.service.TuyaSdkService; import com.xhai.iot.ui.adapter.HomeDeviceAdapter; +import com.xhai.iot.util.ActivityEventBus; import com.xhai.iot.util.SessionManager; import com.xhai.iot.util.ThemeManager; import com.thingclips.smart.sdk.api.IDevListener; @@ -93,6 +94,8 @@ public class HomeFragment extends Fragment { loadRecentActivities(); // 注册设备状态回调,物理开关/远程状态变化时实时刷新列表 TuyaSdkService.registerStatusCallback(deviceStatusCallback); + // 注册动态事件回调:任意控制落库成功后,首页「近期动态」立即刷新 + ActivityEventBus.register(activityEventListener); } @Override @@ -100,6 +103,11 @@ public class HomeFragment extends Fragment { super.onDestroyView(); unregisterAllTuyaListeners(); TuyaSdkService.unregisterStatusCallback(deviceStatusCallback); + ActivityEventBus.unregister(activityEventListener); + if (activityRefreshTask != null) { + activityRefreshHandler.removeCallbacks(activityRefreshTask); + activityRefreshTask = null; + } } @Override @@ -112,6 +120,8 @@ public class HomeFragment extends Fragment { adapter.notifyDataSetChanged(); } loadDevicesFromBackend(); + // 兜底:页面回到前台时同步一次近期动态(覆盖进程内事件丢失的情况) + scheduleActivityRefresh(); } } @@ -122,9 +132,35 @@ public class HomeFragment extends Fragment { if (!hidden && adapter != null && isAdded()) { adapter.setAccentColor(ThemeManager.getInstance(requireContext()).accent().value); 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); + } + // ==================== 刷新节流(避免高频全量重绑导致界面闪动) ==================== /** diff --git a/Android/app/src/main/java/com/xhai/iot/util/ActivityEventBus.java b/Android/app/src/main/java/com/xhai/iot/util/ActivityEventBus.java new file mode 100644 index 0000000..0faf478 --- /dev/null +++ b/Android/app/src/main/java/com/xhai/iot/util/ActivityEventBus.java @@ -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; + +/** + * 设备动态(操控记录)事件总线。 + * + *

首页「近期动态」是后端 device_activity_log 的快照,控制动作本身走涂鸦 SDK 直连、 + * 不经后端,所以必须由客户端在动态落库成功之后主动通知 UI 刷新,否则首页列表 + * 一直停留在进入页面那一刻的静态数据。

+ * + *

实现方式与 {@code TuyaSdkService} 的状态回调保持一致:进程级静态回调列表, + * 页面注册/注销,事件在主线程派发。

+ */ +public final class ActivityEventBus { + + /** 动态变更监听 */ + public interface Listener { + /** + * @param deviceId 发生动态的设备ID,可能为 null(表示全局刷新) + */ + void onActivityChanged(String deviceId); + } + + private static final List 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 snapshot; + synchronized (listeners) { + if (listeners.isEmpty()) return; + snapshot = new ArrayList<>(listeners); + } + MAIN.post(() -> { + for (Listener l : snapshot) { + try { + l.onActivityChanged(deviceId); + } catch (Exception ignored) { + } + } + }); + } +}