Jetpack Compose中Android新Splash Screen卡顿问题求助
问题排查与修复方案
核心问题分析
- 状态无法同步:
MainActivity中定义的keepSplashOpened是普通变量,仅在onCreate时取一次viewModel.state的值,后续viewModel中state的更新无法同步到该变量,导致setKeepOnScreenCondition始终认为需要保持启动页显示。 - 状态类设计问题:
SplashState中的keepSplashOpened使用var,但搭配mutableStateOf时,数据类应保持不可变性(用val),因为mutableStateOf是通过替换整个state对象触发重组,var会破坏状态更新的可靠性。 - 数据流收集方式不当:
SplashViewModel中对readOnBoardingUseCase()的collect会持续监听数据流,若DataStore的数据流未正确终止,可能导致不必要的资源占用,甚至间接影响启动页关闭逻辑。
具体修复步骤
1. 修正SplashState的不可变性
data class SplashState( val graphs: String? = null, val keepSplashOpened: Boolean = true // 将var改为val,保持数据类不可变 )
2. 调整SplashViewModel的状态更新逻辑
@HiltViewModel class SplashViewModel @Inject constructor( private val readOnBoardingUseCase: ReadOnBoardingUseCase ) : ViewModel() { var state by mutableStateOf(SplashState()) private set // 限制外部直接修改状态,通过方法更新 init { viewModelScope.launch { // 仅读取一次DataStore中的onboarding状态,而非持续监听 val completed = readOnBoardingUseCase().first() state = state.copy( graphs = if (completed) Graph.HOME else Graph.WELCOME, keepSplashOpened = false ) } } // 提供外部更新启动页状态的方法 fun updateKeepSplashOpened(keep: Boolean) { state = state.copy(keepSplashOpened = keep) } }
3. 修复MainActivity的启动页状态监听逻辑
@AndroidEntryPoint class MainActivity : ComponentActivity() { private val viewModel: SplashViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 用StateFlow追踪启动页保持状态,确保能感知ViewModel的状态变化 val keepSplashOpened = MutableStateFlow(viewModel.state.keepSplashOpened) // 生命周期绑定,监听ViewModel的state变化 lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.state.collect { newState -> keepSplashOpened.value = newState.keepSplashOpened } } } installSplashScreen().setKeepOnScreenCondition { // 实时获取最新的状态值 keepSplashOpened.value } setContent { val window = rememberWindowSizeClass() KippTheme(window) { val currentState by viewModel.state.collectAsState() RootNavigationGraph( graph = currentState.graphs, onDataLoaded = { // 若需要手动触发关闭,调用ViewModel的更新方法 viewModel.updateKeepSplashOpened(false) } ) } } } }
额外排查点
- 检查
ReadOnBoardingUseCase的实现,确保DataStore的读取逻辑无阻塞(如是否在主线程执行耗时操作)。 - 验证引导页点击确认按钮后,
DataStore是否正确写入completed = true的状态。 - 确保
Graph.HOME和Graph.WELCOME的定义正确,避免导航图加载异常导致启动页无法关闭。
内容的提问来源于stack exchange,提问作者Daniel Lopes
相关产品推荐
相关产品推荐

