Android Jetpack Compose中Fragment内获取Activity ViewModel返回null问题
问题根因
你拿到的是两个完全不同的ViewModel实例:
- 你在Fragment中通过
by activityViewModels()获取的是Activity维度的ViewModel实例,存储在Activity的ViewModelStore中 - Compose的
viewModel()方法默认从最近的ViewModelStoreOwner取实例,如果你是在Fragment的setContent中编写的Compose代码,默认的ViewModelStoreOwner就是当前Fragment,所以直接调用viewModel()拿到的是Fragment级别的实例,和你Fragment中声明的Activity级别的实例完全无关,内部未赋值的formItem自然为null
解决方案
两种方案按需选择:
- 方案一:直接传参,把Fragment中已经获取到的Activity级别ViewModel直接传给Composable,逻辑最简单也不会出问题
// Fragment中setContent时传参 setContent { YourBirthdayScreen(birthdayViewModel = birthdayViewModel) } // Composable中直接使用传入的实例,不需要再调用viewModel()获取 @Composable fun YourBirthdayScreen(birthdayViewModel: BirthdayViewModel) { val formItem by birthdayViewModel.birthdayFormItem.observeAsState() // 后续业务逻辑 } - 方案二:在Compose中显式指定ViewModelStoreOwner为Activity,直接获取Activity级别的实例
注意如果你的Composable可能在非Activity上下文环境渲染,需要补充强转失败的兼容逻辑避免崩溃@Composable fun YourBirthdayScreen() { val activity = LocalContext.current as? Activity ?: return val birthdayViewModel: BirthdayViewModel = viewModel( viewModelStoreOwner = activity ) val formItem by birthdayViewModel.birthdayFormItem.observeAsState() // 后续业务逻辑 }
关于Debug报错的说明
你遇到的Cannot find local variable 'formItem'报错是Android Studio对Compose委托属性的解析兼容问题,不是代码逻辑错误,直接查看birthdayViewModel.birthdayFormItem.value就可以正常看到值,升级到最新稳定版Android Studio可以解决这个问题。
关于Gradle兼容的疑问
99%概率不是Gradle版本兼容问题,除非你使用的lifecycle、compose依赖版本跨度极大存在已知bug,可以确认下你的lifecycle版本在2.5.0以上、compose版本在1.2.0以上,版本匹配的情况下不会出现这类兼容问题。
内容的提问来源于stack exchange,提问作者Charles Woodson
相关产品推荐
相关产品推荐

