Fragment中ViewModel旋转保留问题:传入Activity才生效?
嗨,我来帮你理清这个ViewModel和Fragment生命周期的问题~
传入Activity是否为正确用法?
完全正确,这不仅是合法用法,更是在需要跨Fragment共享状态、或者希望ViewModel在屏幕旋转这类配置变更中保留状态时的推荐做法。
当你把Activity传入ViewModelProviders.of(activity)(或者现在更推荐的ViewModelProvider(requireActivity()))时,ViewModel会绑定到宿主Activity的生命周期。Android框架在配置变更(比如屏幕旋转)时会重建Activity,但会自动保留绑定到Activity的ViewModel实例,所以ViewModel里的所有状态数据都不会丢失。
传入Fragment时无法保留ViewModel是否属于预期行为?
是的,这完全是框架的预期行为。
默认情况下,屏幕旋转时,Activity会被重建,依附于它的Fragment也会跟着被销毁并重新创建一个新实例。当你调用ViewModelProviders.of(this)(这里的this是Fragment)时,ViewModel会绑定到当前Fragment的生命周期——旧Fragment被销毁时,对应的ViewModel也会被框架清理掉;新Fragment实例创建后,会初始化一个全新的ViewModel,自然就丢失了之前的状态。
(补充:旧版本里有setRetainInstance(true)的方式让Fragment实例保留,但这种做法已经不推荐和ViewModel配合使用,ViewModel的设计就是为了替代这种老旧的状态保留方案。)
正确实现代码示例
这里给你调整后的代码,用AndroidX推荐的API来实现状态保留:
class MainFragment : Fragment() { // 绑定到Activity生命周期的ViewModel private lateinit var viewModel: MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 使用requireActivity()获取宿主Activity作为ViewModel的owner viewModel = ViewModelProvider(requireActivity()).get(MainViewModel::class.java) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 观察ViewModel中的LiveData,用viewLifecycleOwner确保UI生命周期安全 viewModel.userData.observe(viewLifecycleOwner) { data -> // 这里更新你的UI组件,比如TextView显示数据 } } } // 对应的ViewModel类 class MainViewModel : ViewModel() { // 示例:保存需要保留的状态数据 val userData = MutableLiveData<String>() // 其他业务逻辑方法 fun updateData(newData: String) { userData.value = newData } }
额外说明
- 如果你的ViewModel不需要跨Fragment共享,只是希望单个Fragment在旋转时保留状态,绑定到Activity依然是最优解——因为Fragment本身会在旋转时重建,绑定到Fragment的ViewModel无法存活。
- 现在AndroidX已经废弃了
ViewModelProviders类,推荐直接使用ViewModelProvider类,代码更简洁也更符合最新的架构规范。
内容的提问来源于stack exchange,提问作者jpgw

