installSplashScreen().setKeepOnScreenCondition失效问题排查
问题原因分析
你的代码存在两个核心问题导致启动屏提前关闭:
StateFlow状态变化未被正确监听:
setKeepOnScreenCondition中直接读取splashScreenViewModel.isLoading.value只是获取当前快照值,当isLoading的StateFlow更新为Success时,系统不会自动重新评估这个条件,无法及时响应状态变化调整启动屏显示状态。初始化逻辑执行过快:
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
相关产品推荐
相关产品推荐

