如何让SplashScreen等待MainActivity的ViewModel满足指定条件?
如何让Jetpack Compose启动页等待AppViewModel的状态就绪?
我遇到了这样的问题:在Jetpack Compose项目中,想要让启动页等待AppViewModel里的状态变量变为true,但初始代码存在逻辑矛盾:
初始代码如下:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { installSplashScreen().setKeepOnScreenCondition {appViewModel.isReady} super.onCreate(savedInstanceState) setContent { val appViewModel: AppViewModel = viewModel(factory = AppViewModel.factory) val uiState by appViewModel.uiStateFlow.collectAsState() // 其他Composable代码 } } }
问题点很明确:调用appViewModel.isReady时,appViewModel还未定义——它是在setContent的Composable函数内部声明的。如果尝试在setContent之前用Composable的viewModel()方法声明,会报错“@Composable invocations can only happen within the context of @Composable function”,同时根据官方文档,installSplashScreen()必须在super.onCreate()之前调用,这就陷入了两难。
解决方案
最终我找到的可行写法是使用Activity级别的viewModels()扩展方法,而非Composable上下文里的viewModel():
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { val appViewModel by viewModels<AppViewModel> { AppViewModel.factory } installSplashScreen().setKeepOnScreenCondition { appViewModel.isLoading } super.onCreate(savedInstanceState) setContent { val uiState by appViewModel.uiStateFlow.collectAsState() // 其他Composable代码 } } }
原理说明
viewModels()是ComponentActivity的扩展方法,它可以在Activity的onCreate方法中直接获取ViewModel实例,不需要依赖Composable上下文,完美避开了之前的报错问题。这样就能在调用installSplashScreen()之前初始化ViewModel,并用它的状态(比如示例里的isLoading)来控制启动页是否保持显示,直到准备工作完成。
内容的提问来源于stack exchange,提问作者Elaws
相关产品推荐
相关产品推荐

