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

installSplashScreen().setKeepOnScreenCondition失效问题排查

问题原因分析

你的代码存在两个核心问题导致启动屏提前关闭:

  1. StateFlow状态变化未被正确监听:
    setKeepOnScreenCondition 中直接读取 splashScreenViewModel.isLoading.value 只是获取当前快照值,当 isLoading 的StateFlow更新为 Success 时,系统不会自动重新评估这个条件,无法及时响应状态变化调整启动屏显示状态。

  2. 初始化逻辑执行过快:
    preferences.readOnboardingCompleted() 是同步操作,viewModelScope.launch 中的代码会瞬间执行完毕,_isLoading 很快切换为 Success,导致启动屏仅能显示极短时间。如果你的需求是等待真正的异步加载(比如网络请求、数据库初始化),当前逻辑没有预留等待时间;如果只是希望启动屏至少显示一段时间提升体验,也需要补充延迟逻辑。

修复方案

步骤1:统一使用StateFlow管理状态

将ViewModel中的启动目标改为StateFlow,保持状态管理的一致性,同时可添加可选延迟确保启动屏显示时长:

class SplashScreenViewModel @Inject constructor(
    private val preferences: Preferences
) : ViewModel() {

    private val _isLoading = MutableStateFlow<RequestState>(RequestState.Loading)
    val isLoading = _isLoading.asStateFlow()

    private val _startDestination = MutableStateFlow("welcome")
    val startDestination = _startDestination.asStateFlow()

    init {
        viewModelScope.launch {
            // 可选:设置最小显示时长,避免闪屏(无实际异步任务时使用)
            delay(1500)
            
            val onboardingCompleted = preferences.readOnboardingCompleted()
            _startDestination.value = if (onboardingCompleted) "overview" else "welcome"
            
            _isLoading.value = RequestState.Success()
        }
    }
}

步骤2:在Activity中正确监听StateFlow状态

在MainActivity中,使用生命周期感知的方式收集StateFlow,维护本地状态跟踪加载状态,确保启动屏条件能响应状态变化:

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

    @Inject
    lateinit var splashScreenViewModel: SplashScreenViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 本地状态跟踪加载状态,用于启动屏条件检查
        var isLoading by mutableStateOf(true)

        // 生命周期安全地收集StateFlow
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                splashScreenViewModel.isLoading.collect { state ->
                    isLoading = state is RequestState.Loading
                }
            }
        }

        // 设置启动屏保持条件
        installSplashScreen().setKeepOnScreenCondition { isLoading }

        setContent {
            HealthTheme {
                // 收集启动目标的状态
                val startDestination by splashScreenViewModel.startDestination.collectAsState()
                val snackbarHostState = remember { SnackbarHostState() }

                Scaffold(
                    modifier = Modifier.fillMaxSize(),
                    snackbarHost = { SnackbarHost(snackbarHostState) }
                ) { paddingValues ->
                    val navController = rememberNavController()
                    NavHost(
                        navController = navController,
                        startDestination = startDestination
                    ) {
                        // 你的导航页面定义...
                    }
                }
            }
        }
    }
}

关键说明

  • repeatOnLifecycle:确保仅在Activity处于STARTED状态时收集Flow,避免内存泄漏。
  • 本地mutableStateOf:让启动屏的条件检查能实时响应StateFlow的状态变化,当加载完成时自动关闭启动屏。
  • 可选延迟:如果没有实际的异步加载任务,添加delay(1500)可以让启动屏至少显示1.5秒,优化用户体验。

内容的提问来源于stack exchange,提问作者Martín

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 19:03:31