You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose Activity中变量声明位置及断网重连逻辑实现咨询

问题分析与优化方案

原代码的核心问题

  1. 状态管理缺陷:hasBeenOfflineForMillis 声明在 onCreate 方法内,当Activity因配置变化(如屏幕旋转)重建时,变量会被重置;且当Activity进入后台,repeatOnLifecycle 暂停collect后,再次回到前台时会重新触发onEach逻辑,覆盖原本的断网开始时间,导致断网时长计算错误。
  2. 逻辑漏洞:网络恢复时将变量赋值为断网时长,单次离线恢复的计算看似正常,但结合Activity生命周期重启场景,会出现时长统计断层,无法准确累计完整的断网时间。
  3. 职责不清晰:Activity承担了网络状态处理和业务逻辑判断的双重职责,不符合MVVM架构的单一原则。

优化方案:将状态与逻辑移至ViewModel

把断网时长记录、触发条件判断等逻辑放到ViewModel中,利用ViewModel的生命周期优势(不受Activity重建影响),同时让Activity仅负责UI层面的响应。

1. ViewModel 实现

@HiltViewModel
class MainActivityViewModel @Inject constructor(
    private val networkMonitor: NetworkMonitor
) : ViewModel() {
    // 用SharedFlow通知Activity执行同步操作
    private val _triggerSync = MutableSharedFlow<Unit>()
    val triggerSync = _triggerSync.asSharedFlow()

    init {
        viewModelScope.launch {
            // 仅在断网开始时记录时间,避免重复赋值
            var offlineStartTime: Long? = null
            
            networkMonitor.isOnline.collect { isOnline ->
                when (isOnline) {
                    false -> {
                        // 断网时,仅当未记录开始时间才赋值
                        if (offlineStartTime == null) {
                            offlineStartTime = System.currentTimeMillis()
                        }
                    }
                    true -> {
                        // 网络恢复时计算断网时长
                        offlineStartTime?.let { startTime ->
                            val offlineDuration = System.currentTimeMillis() - startTime
                            if (offlineDuration > 30000) {
                                // 满足条件,发送同步信号
                                _triggerSync.emit(Unit)
                            }
                            // 重置断网开始时间,准备下一次判断
                            offlineStartTime = null
                        }
                    }
                }
            }
        }
    }
}

2. Activity 实现

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

    private val mainActivityViewModel: MainActivityViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        val splashScreen = installSplashScreen()
        super.onCreate(savedInstanceState)

        lifecycleScope.launch {
            // 仅在Activity处于STARTED状态时响应同步信号
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                mainActivityViewModel.triggerSync.collect {
                    // 执行同步操作
                    syncRepositories()
                }
            }
        }

        // Other code...
    }

    private fun syncRepositories() {
        // 实现你的仓库同步逻辑
    }
}

方案优势

  • 状态持久化:ViewModel的生命周期独立于Activity,配置变化或Activity后台切换时,断网开始时间不会丢失,确保时长计算准确。
  • 职责分离:ViewModel负责业务逻辑判断,Activity仅处理UI层面的操作,符合MVVM架构规范。
  • 生命周期安全:Activity使用repeatOnLifecycle(STARTED)收集同步信号,确保仅在前台时执行操作,避免后台不必要的资源消耗。
  • 逻辑严谨:仅在断网初始时记录开始时间,网络恢复后重置,避免重复计算或错误覆盖。

内容的提问来源于stack exchange,提问作者Giuliopime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:37:05