fix: 红点不显示——SharedFlow(replay=0)事件竞争
根因:EventBus用MutableSharedFlow(replay=0,buffer=0), MainActivity和HomeFragment同时collect,NewTaskArrived 中间事件在emit时挂起(无缓冲),HomeFragment收不到。 修复:去掉NewTaskArrived中间事件,HomeFragment直接在 MqttMessageReceived type=1中处理: 1. 调 notificationManager.onNewTaskMessage() 2. 直接调 activity.showNotificationBanner() 显示横幅 3. fetchStatistics(checkDots=true) 刷新红点 架构简化: - MainActivity不再监听MQTT type=1(去掉observeMqttMessages) - NotificationManager不再emit事件(去掉EventBus依赖) - 去抖合并后通过回调onPendingCountChanged通知UI Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,16 +7,9 @@ import android.view.View
|
|||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.xiaoqu.watch.databinding.ActivityMainBinding
|
import com.xiaoqu.watch.databinding.ActivityMainBinding
|
||||||
import com.xiaoqu.watch.event.AppEvent
|
|
||||||
import com.xiaoqu.watch.event.EventBus
|
|
||||||
import com.xiaoqu.watch.service.manager.NotificationManager
|
|
||||||
import com.xiaoqu.watch.service.manager.SystemStateMonitor
|
import com.xiaoqu.watch.service.manager.SystemStateMonitor
|
||||||
import com.xiaoqu.watch.ui.widget.NotificationBannerView
|
import com.xiaoqu.watch.ui.widget.NotificationBannerView
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.SupervisorJob
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
@@ -32,17 +25,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
/** 系统状态监听器(电量、蓝牙状态) */
|
/** 系统状态监听器(电量、蓝牙状态) */
|
||||||
@Inject lateinit var systemStateMonitor: SystemStateMonitor
|
@Inject lateinit var systemStateMonitor: SystemStateMonitor
|
||||||
/** 消息通知管理器 */
|
/** 通知横幅(HomeFragment 需访问) */
|
||||||
@Inject lateinit var notificationManager: NotificationManager
|
|
||||||
/** 事件总线 */
|
|
||||||
@Inject lateinit var eventBus: EventBus
|
|
||||||
|
|
||||||
/** 通知横幅(HomeFragment 需访问设置点击回调) */
|
|
||||||
lateinit var notificationBanner: NotificationBannerView
|
lateinit var notificationBanner: NotificationBannerView
|
||||||
|
|
||||||
/** Activity 协程作用域 */
|
|
||||||
private val activityScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
@@ -68,9 +53,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
// 初始化通知横幅
|
// 初始化通知横幅
|
||||||
notificationBanner = binding.notificationBanner
|
notificationBanner = binding.notificationBanner
|
||||||
|
|
||||||
// 监听 MQTT 新任务消息,显示横幅
|
|
||||||
observeMqttMessages()
|
|
||||||
|
|
||||||
Timber.d("MainActivity created")
|
Timber.d("MainActivity created")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,27 +62,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
notificationBanner.destroy()
|
notificationBanner.destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== MQTT 新任务 → 通知横幅 =====
|
// ===== 通知横幅(由 HomeFragment 调用显示) =====
|
||||||
|
|
||||||
/** 监听 MQTT 消息和通知事件 */
|
/** 显示通知横幅(供 HomeFragment 调用) */
|
||||||
private fun observeMqttMessages() {
|
fun showNotificationBanner(count: Int) {
|
||||||
activityScope.launch {
|
notificationBanner.show(count)
|
||||||
eventBus.events.collect { event ->
|
}
|
||||||
when (event) {
|
|
||||||
is AppEvent.MqttMessageReceived -> {
|
|
||||||
if (event.type == 1) {
|
|
||||||
// 交给 NotificationManager 处理(去抖+合并+震动+亮屏)
|
|
||||||
notificationManager.onNewTaskMessage(event.rawJson)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// NotificationManager 处理完后发出事件 → 显示/更新横幅
|
|
||||||
is AppEvent.NewTaskArrived -> {
|
|
||||||
notificationBanner.show(event.count)
|
|
||||||
}
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 下拉手势检测(Activity 级别,不可能被子 View 拦截) =====
|
// ===== 下拉手势检测(Activity 级别,不可能被子 View 拦截) =====
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import com.xiaoqu.watch.data.task.TaskStatistics
|
|||||||
import com.xiaoqu.watch.device.screen.ScreenController
|
import com.xiaoqu.watch.device.screen.ScreenController
|
||||||
import com.xiaoqu.watch.device.sensor.VibrationController
|
import com.xiaoqu.watch.device.sensor.VibrationController
|
||||||
import com.xiaoqu.watch.device.sensor.VibrationDefaults
|
import com.xiaoqu.watch.device.sensor.VibrationDefaults
|
||||||
import com.xiaoqu.watch.event.AppEvent
|
|
||||||
import com.xiaoqu.watch.event.EventBus
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
@@ -27,8 +25,7 @@ import javax.inject.Singleton
|
|||||||
@Singleton
|
@Singleton
|
||||||
class NotificationManager @Inject constructor(
|
class NotificationManager @Inject constructor(
|
||||||
private val vibrationController: VibrationController,
|
private val vibrationController: VibrationController,
|
||||||
private val screenController: ScreenController,
|
private val screenController: ScreenController
|
||||||
private val eventBus: EventBus
|
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
/** 去抖间隔(毫秒) */
|
/** 去抖间隔(毫秒) */
|
||||||
@@ -73,6 +70,9 @@ class NotificationManager @Inject constructor(
|
|||||||
/** 协程作用域 */
|
/** 协程作用域 */
|
||||||
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||||
|
|
||||||
|
/** 去抖合并后的回调(通知 UI 更新横幅数字) */
|
||||||
|
var onPendingCountChanged: ((Int) -> Unit)? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理 MQTT type=1 新任务消息
|
* 处理 MQTT type=1 新任务消息
|
||||||
* 去抖策略:1s 窗口内的消息暂存,窗口结束后合并处理(不丢弃)
|
* 去抖策略:1s 窗口内的消息暂存,窗口结束后合并处理(不丢弃)
|
||||||
@@ -104,8 +104,8 @@ class NotificationManager @Inject constructor(
|
|||||||
for (json in jsons) {
|
for (json in jsons) {
|
||||||
processMessageSilent(json) // 只加 ID,不重复震动
|
processMessageSilent(json) // 只加 ID,不重复震动
|
||||||
}
|
}
|
||||||
// 合并后统一发一次事件
|
// 合并后通知 UI 更新数字
|
||||||
notifyUi()
|
onPendingCountChanged?.invoke(pendingCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,8 +128,7 @@ class NotificationManager @Inject constructor(
|
|||||||
vibrationController.executePattern(pattern)
|
vibrationController.executePattern(pattern)
|
||||||
}
|
}
|
||||||
screenController.turnOn()
|
screenController.turnOn()
|
||||||
|
// UI 更新(横幅+红点)由调用方处理,不再通过 EventBus
|
||||||
notifyUi()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 静默处理(只加 ID,不震动不亮屏,用于合并暂存消息) */
|
/** 静默处理(只加 ID,不震动不亮屏,用于合并暂存消息) */
|
||||||
@@ -149,12 +148,7 @@ class NotificationManager @Inject constructor(
|
|||||||
Timber.d("通知: 当前未读 ${_pendingTaskIds.size}")
|
Timber.d("通知: 当前未读 ${_pendingTaskIds.size}")
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 通知 UI 更新(横幅+红点) */
|
// notifyUi 已移除,UI 更新改由调用方(HomeFragment)直接处理
|
||||||
private fun notifyUi() {
|
|
||||||
scope.launch {
|
|
||||||
eventBus.emit(AppEvent.NewTaskArrived(_pendingTaskIds.toList(), _pendingTaskIds.size))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 消费所有未读消息(用户点击提示条/横幅查看全部) */
|
/** 消费所有未读消息(用户点击提示条/横幅查看全部) */
|
||||||
fun consumeAll() {
|
fun consumeAll() {
|
||||||
|
|||||||
@@ -130,6 +130,12 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
|
|
||||||
// 监听打卡状态
|
// 监听打卡状态
|
||||||
observePunchState()
|
observePunchState()
|
||||||
|
|
||||||
|
// 去抖合并后更新横幅数字
|
||||||
|
notificationManager.onPendingCountChanged = { count ->
|
||||||
|
(activity as? com.xiaoqu.watch.app.MainActivity)?.showNotificationBanner(count)
|
||||||
|
fetchStatistics(checkDots = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@@ -175,12 +181,13 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
// 清理 Activity 回调,避免泄漏
|
// 清理回调,避免泄漏
|
||||||
(activity as? com.xiaoqu.watch.app.MainActivity)?.let {
|
(activity as? com.xiaoqu.watch.app.MainActivity)?.let {
|
||||||
it.onSwipeDown = null
|
it.onSwipeDown = null
|
||||||
it.onBackKeyPressed = null
|
it.onBackKeyPressed = null
|
||||||
it.notificationBanner.onClick = null
|
it.notificationBanner.onClick = null
|
||||||
}
|
}
|
||||||
|
notificationManager.onPendingCountChanged = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 打卡面板 =====
|
// ===== 打卡面板 =====
|
||||||
@@ -484,12 +491,6 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
is AppEvent.BluetoothStateChanged -> {
|
is AppEvent.BluetoothStateChanged -> {
|
||||||
statusBar.updateBluetooth(event.isOn)
|
statusBar.updateBluetooth(event.isOn)
|
||||||
}
|
}
|
||||||
// 新任务到达 → 刷新统计 + 累积红点
|
|
||||||
is AppEvent.NewTaskArrived -> {
|
|
||||||
Timber.d("首页: 新任务到达 (${event.count} 条)")
|
|
||||||
fetchStatistics(checkDots = true)
|
|
||||||
setupBannerClick()
|
|
||||||
}
|
|
||||||
// MQTT 消息
|
// MQTT 消息
|
||||||
is AppEvent.MqttMessageReceived -> {
|
is AppEvent.MqttMessageReceived -> {
|
||||||
when (event.type) {
|
when (event.type) {
|
||||||
@@ -498,6 +499,20 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
Timber.d("首页: 收到日常动态")
|
Timber.d("首页: 收到日常动态")
|
||||||
fetchStatistics()
|
fetchStatistics()
|
||||||
}
|
}
|
||||||
|
1 -> {
|
||||||
|
// 新任务 → 直接处理(不走中间事件,避免 SharedFlow 竞争)
|
||||||
|
Timber.d("首页: 收到新任务通知")
|
||||||
|
notificationManager.onNewTaskMessage(event.rawJson)
|
||||||
|
// 显示横幅
|
||||||
|
val count = notificationManager.pendingCount
|
||||||
|
if (count > 0) {
|
||||||
|
(activity as? com.xiaoqu.watch.app.MainActivity)
|
||||||
|
?.showNotificationBanner(count)
|
||||||
|
}
|
||||||
|
// 刷新统计 + 红点
|
||||||
|
fetchStatistics(checkDots = true)
|
||||||
|
setupBannerClick()
|
||||||
|
}
|
||||||
3 -> {
|
3 -> {
|
||||||
// 解绑 → 停止蓝牙 → 清除数据 → 跳绑定页
|
// 解绑 → 停止蓝牙 → 清除数据 → 跳绑定页
|
||||||
Timber.d("首页: 收到解绑消息")
|
Timber.d("首页: 收到解绑消息")
|
||||||
|
|||||||
Reference in New Issue
Block a user