Android屏幕旋转后页面空白,Hilt配合SavedState初始化ViewModel报错如何解决
问题根因
- 你同时使用了Hilt的
@HiltViewModel注解和手动指定SavedStateViewModelFactory,两者逻辑冲突:@HiltViewModel会由Hilt自动完成ViewModel的依赖注入(包括注入SavedStateHandle、业务依赖如ImageListUseCase等),手动指定工厂后,系统会用你传入的工厂实例化ViewModel,而SavedStateViewModelFactory不知道如何注入你自定义的业务依赖,只会尝试调用无参构造函数,因此抛出找不到无参构造器的报错。 - 多余的手动保存状态逻辑:
SavedStateHandle本身已经和宿主Fragment的实例状态绑定,你不需要手动重写onSaveInstanceState触发保存。
修复方案
- 修改Fragment中ViewModel的初始化代码,删除手动传入的工厂:
// 修正前(错误写法) private val imagePickerViewModel: ImagePickerViewModel by viewModels { SavedStateViewModelFactory(activity?.applicationContext as Application, this) } // 修正后(正确写法) private val imagePickerViewModel: ImagePickerViewModel by viewModels()
你的Fragment已经加了@AndroidEntryPoint注解,Hilt会自动注入适配@HiltViewModel的ViewModel工厂,不需要手动配置。
- 删除Fragment中多余的
onSaveInstanceState重写逻辑,不需要手动调用trigger()方法:
// 直接删除这段代码即可 override fun onSaveInstanceState(outState: Bundle) { imagePickerViewModel.trigger() super.onSaveInstanceState(outState) }
- 优化ViewModel中的状态更新逻辑:
savedStateHandle.getLiveData()返回的LiveData会和SavedStateHandle自动同步,你每次更新图片列表时,直接给savedStateHandle对应的key赋值即可,数据会自动持久化,页面旋转重建后自动恢复:
// 示例:当你获取到新的图片列表时调用该方法即可 fun updateImageList(newList: ArrayList<Image>) { savedStateHandle["key"] = Event(newList) }
此时你的_observeImageListData会自动收到更新后的值,不需要额外手动同步。
验证逻辑
修改完成后运行项目,屏幕旋转后ViewModel不会重新走初始化请求逻辑,之前加载的图片列表会自动恢复,不会出现空白页面。
内容的提问来源于stack exchange,提问作者Ahmed Mamdouh
相关产品推荐
相关产品推荐

