首页 > 解决方案 > 将活动的 ViewModel 注入片段的 ViewModel

问题描述

我已经设置了一个非常类似于GithubBrowserSample. 因此,匕首设置是相同的。

考虑有ActivityViewModeland FragmentViewModel,它们具有非零 arg 构造函数,因此它们是ViewModelProviders通过 custom获取的ViewModelProvider.Factory

我想要的是指示匕首ActivityViewModel在以下代码中注入已经创建的实例:


    class FragmentViewModel @Inject constructor(
        private val activityViewModel: ActivityViewModel
        private val foo: Foo
    ) : ViewModel() {
        ...
    }

使用当前声明 Dagger 将创建一个实例,ActivityViewModel无论是否已经存在。

发生这种情况是因为存在一个带@Inject注释的构造函数ActivityViewModel

因此,dagger 可以自由假设,它是提供 to 实例的正确ActivityViewModel方法FragmentViewModel

我知道如何为普通的 Dagger 做东西,但我不知道如何为 Dagger-Android 做这个,这个问题是专门针对 Dagger-Android 设置的。

作为一个肮脏的解决方案,我目前正在手动设置该实例:


    class MyFragment : Fragment {
      ...
      override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this, viewModelFactory).get(FragmentViewModel::class.java)
        viewModel.activityViewModel = ViewModelProviders.of(activity!!, viewModelFactory).get(ActivityViewModel::class.java)
      }
      ...
    }

ViewModel将父母注入孩子的正确方法是ViewModel什么?

标签: androiddagger-2android-architecture-componentsandroid-viewmodeldagger

解决方案


不是问题的答案,而是我提出并目前使用的一种方法。

声明了以下扩展函数:

inline fun <reified T : ViewModel> Fragment.getViewModel(
    factory: ViewModelProvider.Factory = ViewModelProvider.NewInstanceFactory()
) = ViewModelProviders.of(this, factory).get(T::class.java)

inline fun <reified T : ViewModel> Fragment.getParentViewModel(
    factory: ViewModelProvider.Factory = ViewModelProvider.NewInstanceFactory()
) = ViewModelProviders.of(activity!!, factory).get(T::class.java)

然后在片段类中,我们可以声明以下内容:

private val parentViewModel by lazy { getParentViewModel<ParentViewModel>(viewModelFactory) }
private val childViewModel by lazy {
  val field = getViewModel<ChildViewModel>(viewModelFactory)
  field.parentViewModel = parentViewModel
  field
}

推荐阅读