SplashScreen API setKeepOnCondition失效:默认目标跳转异常
问题:启动页提前消失,LoginScreen短暂显示后才跳转主界面
我在MainActivity中需要读取DataStore的值来决定显示LoginScreen还是主界面,因此在调用onCreate()前启用了启动页。随后我使用runBlocking获取值并设置startDestination,预期启动页会在runBlocking执行期间保持显示,但实际启动页提前消失,LoginScreen短暂显示后才跳转到主界面。请问我遗漏了什么?是否只有LaunchedEffect的代码块被阻塞?
var isLoadingDataStoreTokens by remember { mutableStateOf(true) } var startDestination : Destination by remember { mutableStateOf( LoginScreenDestination ) } val tokenManager: AuthTokenManager by inject() LaunchedEffect(Unit) { runBlocking { val authToken = tokenManager.getBearerToken().first() val isGuest = tokenManager.isGuest().first() startDestination = if (authToken != null && isGuest != null) DissertationsScreenDestination else LoginScreenDestination isLoadingDataStoreTokens = false } } splashScreen.setKeepOnScreenCondition { !isLoadingDataStoreTokens }
问题原因
runBlocking的错误使用:LaunchedEffect本身就是协程作用域,嵌套runBlocking会阻塞协程线程,导致状态更新延迟。同时,启动页的setKeepOnScreenCondition依赖状态判断,但线程阻塞会打乱状态更新的时序,使得启动页提前关闭。- 初始导航的提前触发:
startDestination初始值设为LoginScreenDestination,在DataStore读取完成前,导航组件已经先渲染了LoginScreen,后续状态更新只能触发二次跳转,因此出现闪屏。
解决方法
1. 移除runBlocking,直接在协程中挂起读取DataStore
DataStore的getBearerToken()和isGuest()返回Flow,直接用挂起函数first()读取即可,无需额外阻塞线程。
2. 延迟导航触发,避免初始页提前渲染
将startDestination初始设为null,直到DataStore读取完成后再赋值,确保加载期间导航组件不会渲染任何页面。
修改后的代码示例
var isLoadingDataStoreTokens by remember { mutableStateOf(true) } var startDestination : Destination? by remember { mutableStateOf(null) } val tokenManager: AuthTokenManager by inject() LaunchedEffect(Unit) { val authToken = tokenManager.getBearerToken().first() val isGuest = tokenManager.isGuest().first() startDestination = if (authToken != null && isGuest != null) { DissertationsScreenDestination } else { LoginScreenDestination } isLoadingDataStoreTokens = false } splashScreen.setKeepOnScreenCondition { isLoadingDataStoreTokens // 加载状态持续时保持启动页显示 } // 仅当目标页面确定后,才初始化导航 startDestination?.let { dest -> NavHost(navController = navController, startDestination = dest) { // 你的导航路由定义 } }
额外说明
setKeepOnScreenCondition的逻辑调整为isLoadingDataStoreTokens,直接明确“加载中就保持启动页”,避免原逻辑中取反带来的时序误解。- 初始
startDestination设为null,彻底避免加载阶段的无效导航,确保启动页显示到加载完成后,直接跳转目标页面,消除闪屏问题。
内容的提问来源于stack exchange,提问作者Stelios Papamichail
相关产品推荐
相关产品推荐

