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

Jetpack Compose:点击Finish后SplashViewModel的collect重复执行问题

问题原因分析

你遇到的核心问题是DataStore的Flow会持续监听数据变更:

  • SplashViewModel在MainActivity中注入,其生命周期和MainActivity绑定,所以它里面监听DataStore的Flow会一直处于活跃状态。
  • 当OnBoardingViewModel调用saveOnBoardingState修改了onBoardingCompleted的值,DataStore会向Flow发射新的更新值,触发SplashViewModel中collect代码再次执行,进而发送导航事件跳转到Auth图。
解决方案

要实现「collect仅执行一次,点击Finish后不跳转」的需求,可以通过以下两种方式处理:

方式1:使用first()或take(1)限制Flow收集次数

直接让Flow只收集一次初始值,后续DataStore的变更不会再触发collect逻辑。修改SplashViewModel中的代码:

用first()实现

viewModelScope.launch {
    // 只获取一次DataStore的初始值,后续变更不监听
    val completed = dataStore.getOnBoardingCompleted().first()
    val route = if (completed == true) NavigationDestinations.Auth.GRAPH else NavigationDestinations.OnBoarding.GRAPH
    splashEventChannel.send(BaseUiEvent.Navigate(route))
    _isLoading.value = false
}

用take(1)实现

viewModelScope.launch {
    dataStore.getOnBoardingCompleted()
        .take(1) // 仅收集第一个发射的值,之后自动取消监听
        .collect { completed ->
            val route = if (completed == true) NavigationDestinations.Auth.GRAPH else NavigationDestinations.OnBoarding.GRAPH
            splashEventChannel.send(BaseUiEvent.Navigate(route))
            _isLoading.value = false
        }
}

方式2:手动取消Flow收集Job

如果需要保留灵活控制的能力,可以保存collect的Job实例,在导航完成后主动取消监听:

private var onBoardingCollectJob: Job? = null

init {
    onBoardingCollectJob = viewModelScope.launch {
        dataStore.getOnBoardingCompleted().collect { completed ->
            val route = if (completed == true) NavigationDestinations.Auth.GRAPH else NavigationDestinations.OnBoarding.GRAPH
            splashEventChannel.send(BaseUiEvent.Navigate(route))
            _isLoading.value = false
            // 发送导航事件后,取消后续监听
            onBoardingCollectJob?.cancel()
        }
    }
}

// 可选:在ViewModel销毁时确保取消Job
override fun onCleared() {
    super.onCleared()
    onBoardingCollectJob?.cancel()
}
额外注意点
  • 确认MainActivity中没有重复创建SplashViewModel的实例,避免多次触发init逻辑。
  • 检查OnBoarding页面的Finish按钮点击事件,确保仅执行saveOnBoardingState,没有意外触发导航回MainActivity的操作(这会导致SplashViewModel的init再次执行)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 15:03:25