是否可以为ViewModelStore
提供一次自己的ViewModelProviders
实现,而不是默认的实现?
更准确地说,我对向fun clear(vm: ViewModel)
添加ViewModelStore
(或使用索引或类似的东西)功能感兴趣,以便我可以清除自己选择的单个视图模型,而不仅仅是使用内置的ViewModelStore#clear
:
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.onCleared();
}
mMap.clear();
}
清除所有视图模型。
最佳答案
首先,我认为您应该而不是考虑这样做,因为这是Architecture Components库的实现细节。通过调整用例以匹配ViewModel
的API公开的准则/合同,您很可能应该提出一个更好的解决方案。
尽管如此,让我们研究一下这样做的可能性。
这是我们为了获得ViewModel
实现而应该使用的代码:
val viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
此代码将导致的结果是,它将创建
HolderFragment
的实例,该实例是保留的片段,并将其附加到this
的片段管理器(可能是FragmentActivity
的片段管理器或Fragment
的child fragment manager)。此
HolderFragment
将添加一个 HolderFragment.HOLDER_TAG
,因此我们能够从片段管理器中获取此片段的实例。val holderFragment = supportFragmentManager.findFragmentByTag("android.arch.lifecycle.state.StateProviderHolderFragment") as HolderFragment
是
HolderFragment
,它创建ViewModelStore
和keeps that instance as a private field的实例。该字段存在一个吸气剂,但不存在一个setter,这意味着“替代”该对象的唯一方法是使用反射。但是在此之前,让我们尝试编写一个
ViewModelStore
类的自定义实现:class MyViewModelStore : ViewModelStore() {
private val mMap = HashMap<String, ViewModel>()
internal fun put(key: String, viewModel: ViewModel) {
val oldViewModel = mMap.put(key, viewModel)
oldViewModel?.onCleared() // COMPILATION ERROR -> Cannot access 'onCleared': it is protected/*protected and package*/ in 'ViewModel'
}
internal operator fun get(key: String): ViewModel? {
return mMap[key]
}
override fun clear() {
for (vm in mMap.values) {
vm.onCleared() // COMPILATION ERROR -> Cannot access 'onCleared': it is protected/*protected and package*/ in 'ViewModel'
}
mMap.clear()
}
}
不幸的是,我们无法做到这一点,因为
ViewModel#onCleared()
has a protected
package access使得我们无法在android.arch.lifecycle
包之外调用它。同样,我们可以使用反射来做到这一点(但这有多好?)。尽管没有(我)建议,但似乎也不可能做到(不使用反射)。