Fragment setRetainInstance()已废弃,对应的替代实现方案是什么?
Fragment
setRetainInstance() 废弃后的状态保留方案 官方废弃setRetainInstance()的核心原因是该API容易引发内存泄漏、生命周期管理异常,推荐优先使用ViewModel实现状态留存,适配99%的原有业务场景。
前置依赖配置(Module级build.gradle的dependencies块添加)
implementation "androidx.fragment:fragment-ktx:1.6.1" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
方案1:普通状态留存(配置变更时保留数据/状态不丢失)
1. 定义ViewModel存储需要保留的状态
import androidx.lifecycle.ViewModel class HomeViewModel : ViewModel() { // 所有需要保留的状态、数据都存储在此处 var userDataList: MutableList<String> = mutableListOf() var currentPagerPosition: Int = 0 // 支持存储无法序列化的复杂对象、异步任务实例等 }
2. Fragment中使用ViewModel
import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import android.os.Bundle class HomeFragment: Fragment (){ // 通过viewModels扩展获取ViewModel实例,配置变更后重建Fragment时拿到的是同一个实例 private val viewModel: HomeViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?){ super.onCreate(savedInstanceState) // 不再需要写retainInstance = true if (viewModel.userDataList.isEmpty()) { // 首次创建Fragment时加载初始数据 loadInitData() } else { // 配置变更后重建Fragment时直接复用已有数据 renderUi(viewModel.userDataList, viewModel.currentPagerPosition) } } private fun loadInitData() { // 模拟数据加载逻辑 viewModel.userDataList = mutableListOf("数据1", "数据2", "数据3") viewModel.currentPagerPosition = 1 renderUi(viewModel.userDataList, viewModel.currentPagerPosition) } private fun renderUi(data: List<String>, position: Int) { // 此处写UI渲染逻辑 } }
方案2:进程杀死后也能恢复的持久化状态留存
如果需要状态在应用进程被系统主动杀死后重启也能恢复,可以配合SavedStateHandle实现:
1. 带SavedStateHandle的ViewModel
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel class HomeViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() { // 定义需要持久化保留的状态 var currentPage: Int get() = savedStateHandle["CURRENT_PAGE"] ?: 0 set(value) = savedStateHandle.set("CURRENT_PAGE", value) // 临时状态也可以正常存在ViewModel中 var tempList: MutableList<String> = mutableListOf() }
2. Fragment中使用方式和方案1完全一致
private val viewModel: HomeViewModel by viewModels()
注意:配置变更时Fragment本身依然会走正常的销毁重建流程,但状态全部存储在ViewModel中,重建后可以直接恢复,和原
retainInstance = true的业务效果完全一致,且避免了原API可能导致的内存泄漏、生命周期异常问题。
内容的提问来源于stack exchange,提问作者Kennedy
相关产品推荐
相关产品推荐

