Fragment中ViewModel旋转后无法保留实例问题排查
解决Fragment旋转后ViewModel重建的问题
问题根源
你当前的代码存在两个核心问题:
- MainActivity每次重建都会创建新Fragment实例:在
onCreate方法中,无论savedInstanceState是否为空,都直接创建并替换新的VideoFragment。设备旋转导致Activity重建时,系统本可恢复原Fragment实例,但你强制创建新Fragment,导致原Fragment及其ViewModel被销毁。 - ViewModel绑定Fragment实例生命周期:当Fragment被重新创建时,对应的
ViewModelStore会重置,调用ViewModelProvider(this)会生成新的ViewModel实例。
解决方案
方案1:让ViewModel绑定Fragment生命周期(旋转时保留)
修复MainActivity代码,仅在Activity首次创建时添加Fragment,配置变化时由系统自动恢复原Fragment:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 仅在首次创建时初始化Fragment,配置变化时跳过 if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .addToBackStack(null) .replace(R.id.main_container, VideoFragment()) .commit() } } }
Fragment中保持原有ViewModel获取方式即可:
class VideoFragment: Fragment() { lateinit var viewModel: VideoViewModel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // 绑定Fragment生命周期,Fragment被系统恢复时复用原ViewModel viewModel = ViewModelProvider(this).get(VideoViewModel::class.java) return inflater.inflate(R.layout.fragment_video, container, false) } }
设备旋转后,Fragment会被系统恢复,对应的ViewModel也会保留,不会重新实例化。
方案2:让ViewModel绑定Activity生命周期(跨Fragment共享)
如果业务需要ViewModel在Activity存活期间始终存在(比如多个Fragment共享数据),可使用requireActivity()作为ViewModelStoreOwner:
class VideoFragment: Fragment() { lateinit var viewModel: VideoViewModel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // 绑定Activity生命周期,只要Activity不销毁,ViewModel就不会重建 viewModel = ViewModelProvider(requireActivity()).get(VideoViewModel::class.java) return inflater.inflate(R.layout.fragment_video, container, false) } }
这种方式无需修改Activity代码,但要注意:所有通过该方式获取ViewModel的Fragment会共享同一个实例,直到Activity销毁。
总结
- 若ViewModel仅服务于当前Fragment,且希望随Fragment销毁而销毁:选择方案1。
- 若需要跨Fragment共享数据,或希望ViewModel在Activity生命周期内持久存在:选择方案2。
内容的提问来源于stack exchange,提问作者bboy
相关产品推荐
相关产品推荐

