Jetpack Compose Activity中变量声明位置及断网重连逻辑实现咨询
问题分析与优化方案
原代码的核心问题
- 状态管理缺陷:
hasBeenOfflineForMillis声明在onCreate方法内,当Activity因配置变化(如屏幕旋转)重建时,变量会被重置;且当Activity进入后台,repeatOnLifecycle暂停collect后,再次回到前台时会重新触发onEach逻辑,覆盖原本的断网开始时间,导致断网时长计算错误。 - 逻辑漏洞:网络恢复时将变量赋值为断网时长,单次离线恢复的计算看似正常,但结合Activity生命周期重启场景,会出现时长统计断层,无法准确累计完整的断网时间。
- 职责不清晰: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
相关产品推荐
相关产品推荐

