正如指出的那样,使用架构组件API无法清除单个ViewModel的ViewModelStore。解决此问题的一种可能方案是拥有每个ViewModel的存储区,可以在必要时安全地清除:
class MainActivity : AppCompatActivity() {
val individualModelStores = HashMap<KClass<out ViewModel>, ViewModelStore>()
inline fun <reified VIEWMODEL : ViewModel> getSharedViewModel(): VIEWMODEL {
val factory = object : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return modelClass.newInstance()
}
}
val viewModelStore = this@MainActivity.getIndividualViewModelStore<VIEWMODEL>()
return ViewModelProvider(this.getIndividualViewModelStore<VIEWMODEL>(), factory).get(VIEWMODEL::class.java)
}
val viewModelStore = this@MainActivity.getIndividualViewModelStore<VIEWMODEL>()
return ViewModelProvider(this.getIndividualViewModelStore<VIEWMODEL>(), factory).get(VIEWMODEL::class.java)
}
inline fun <reified VIEWMODEL : ViewModel> getIndividualViewModelStore(): ViewModelStore {
val viewModelKey = VIEWMODEL::class
var viewModelStore = individualModelStores[viewModelKey]
return if (viewModelStore != null) {
viewModelStore
} else {
viewModelStore = ViewModelStore()
individualModelStores[viewModelKey] = viewModelStore
return viewModelStore
}
}
inline fun <reified VIEWMODEL : ViewModel> clearIndividualViewModelStore() {
val viewModelKey = VIEWMODEL::class
individualModelStores[viewModelKey]?.clear()
individualModelStores.remove(viewModelKey)
}
}
使用
getSharedViewModel()
获取一个与Activity生命周期绑定的ViewModel实例:
val yourViewModel : YourViewModel = (requireActivity() as MainActivity).getSharedViewModel()
稍后,当需要处理共享ViewModel时,请使用clearIndividualViewModelStore<>()
:
(requireActivity() as MainActivity).clearIndividualViewModelStore<YourViewModel>()
在某些情况下,如果不再需要ViewModel(例如,它包含一些敏感的用户数据,如用户名或密码),您会希望尽快清除它。以下是记录每个片段切换时individualModelStores
状态以帮助您跟踪共享ViewModel的方法:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (BuildConfig.DEBUG) {
navController.addOnDestinationChangedListener { _, _, _ ->
if (individualModelStores.isNotEmpty()) {
val tag = this@MainActivity.javaClass.simpleName
Log.w(
tag,
"Don't forget to clear the shared ViewModelStores if they are not needed anymore."
)
Log.w(
tag,
"Currently there are ${individualModelStores.keys.size} ViewModelStores bound to ${this@MainActivity.javaClass.simpleName}:"
)
for ((index, viewModelClass) in individualModelStores.keys.withIndex()) {
Log.w(
tag,
"${index + 1}) $viewModelClass\n"
)
}
}
}
}
}
ViewModelProvider(requireNotNull(targetFragment)).get(MyViewModel::class.java)
- user4003256