Alg*_*gar 5 java inheritance android android-viewmodel android-architecture-components
是否可以提供一次自己的ViewModelStoreforViewModelProviders实现来代替默认的实现?
更准确地说,我有兴趣添加fun clear(vm: ViewModel)(或使用索引或类似的东西)功能,以便ViewModelStore我可以清除我选择的单个视图模型,而不仅仅是使用内置的ViewModelStore#clear:
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.onCleared();
}
mMap.clear();
}
Run Code Online (Sandbox Code Playgroud)
这会清除所有视图模型。
首先,我认为您不应该考虑这样做,因为这是架构组件库的实现细节。通过调整用例以匹配ViewModelAPI 公开的指南/合同,您很可能应该想出更好的解决方案。
尽管如此,让我们研究一下这样做的可能性。
这是我们应该使用的代码来获得实现ViewModel:
val viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
Run Code Online (Sandbox Code Playgroud)
该代码的结果是,它将创建 的实例HolderFragment,它是保留的片段,并将其附加到 的this片段管理器(可能是FragmentActivity的片段管理器或Fragment的子片段管理器)。
这HolderFragment将添加一个HolderFragment.HOLDER_TAG,因此我们能够从片段管理器获取该片段的实例。
val holderFragment = supportFragmentManager.findFragmentByTag("android.arch.lifecycle.state.StateProviderHolderFragment") as HolderFragment
Run Code Online (Sandbox Code Playgroud)
它HolderFragment创建了一个实例ViewModelStore并将该实例保留为私有字段。该字段存在一个 getter,但不存在 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()
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,我们不能这样做,因为ViewModel#onCleared() 有一个protected包访问权限,这使得我们无法在包之外调用它android.arch.lifecycle。同样,我们可以使用反射来做到这一点(但这有多好?)。
尽管(我)没有建议,但这似乎也是无法实现的(不使用反射)。