重写 ViewModelStore

Overriding ViewModelStore

是否可以为 ViewModelProviders 提供一次自己的 ViewModelStore 实现来代替默认实现?

更准确地说,我有兴趣向 ViewModelStore 添加 fun clear(vm: ViewModel)(或使用索引或类似的东西)功能,以便我可以清除我选择的单个视图模型,而不是只需使用内置 ViewModelStore#clear:

public final void clear() {
    for (ViewModel vm : mMap.values()) {
        vm.onCleared();
    }
    mMap.clear();
}

清除所有视图模型。

首先,我认为您 不应该 考虑这样做,因为那是架构组件库的实现细节。由于调整用例以匹配 ViewModels API.

暴露的 guidelines/contracts,您很可能应该想出一个更好的解决方案

尽管如此,让我们研究一下这样做的可能性。

这是代码,我们应该使用它来获得 ViewModel 实现:

val viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)

这段代码的结果是,它会创建一个 HolderFragment, which is a retained fragment, and will attach it to this's fragment manager (might be either FragmentActivity's fragment manager or Fragment's child fragment manager) 的实例。

HolderFragment 将添加一个 HolderFragment.HOLDER_TAG,因此我们可以从片段管理器中获取此片段的实例。

val holderFragment = supportFragmentManager.findFragmentByTag("android.arch.lifecycle.state.StateProviderHolderFragment") as HolderFragment

它是 HolderFragment,它创建了 ViewModelStorekeeps that instance as a private field 的实例。该字段存在 getter,但不存在 setter,这意味着 "substitute" 此对象的唯一方法是使用反射。

但在此之前,让我们尝试编写 ViewModelStore class:

的自定义实现
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 包之外调用它。同样,我们可以使用反射来做到这一点(但这有多好?)。

尽管(我)没有建议,但似乎也无法做到(不使用反射)。