使用ViewModel构造函数而不是ViewModelProvider能够基于参数从Room数据库获取数据

时间:2020-01-11 10:21:00

标签: android viewmodel android-room android-livedata

当基于此codelab将Room数据库与ViewModel和LiveDate结合使用以便使用带有参数的查询时,我没有找到任何解决方案,因此我尝试为视图模型类和存储库创建另一个构造函数类,但我注意到在CodeLab中,他们根本不使用视图模型构造函数,而是使用视图模型提供者,因此我对其进行了更改并使用了
GridView.builder( itemCount: homeList.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2), itemBuilder: (BuildContext context, int index) { return GestureDetector( onTap: () { if (i == 0) { _interstitialAd.show(); } else if (i == 1) { } else if (i == 2) { sendInvite(); }); }, )
代替
new StoryViewModel(getApplication(),"Fiction");

我不知道这是否有问题。
现在可以正常使用,但是如果这样我们为什么不总是使用它呢?
为什么我们要使用视图模型提供程序?

如果我做错了,那么如何根据参数从db检索数据?

谢谢。

2 个答案:

答案 0 :(得分:2)

您不应直接使用viewModel构造函数,因为系统会创建viewModel或从缓存中获取它。如果要将参数传递给viewModel构造函数,则应使用如下所示的viewModel工厂:

class ViewModelFactory(params) : ViewModelProviders.Factory {

     override fun <T : ViewModel> create(modelClass: Class<T>): T {
          return modelClass.getConstructor(params::class.java).newInstance(params);
     }

}

...

override fun onCreate(...) {

  viewModel = ViewModelProviders.of(this, ViewModelFactory(params)).get(MyViewModel::class.java)s
}

答案 1 :(得分:0)

这是一个完整的示例,它是根据我从Pierluigi的答案中学到的知识构建的:

class MyFragment: Fragment() {
    private lateinit var viewModel: ContactViewModel

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        activity?.let { activity ->
            viewModel = ViewModelProvider(
                activity,
                MyViewModelFactory(
                    "mode value",
                    "nickname value"
                )
            ).get(MyViewModel::class.java)
        } ?: throw AssertionError("Unable to get parent activity from fragment")
    }
}

class MyViewModelFactory(val mode: String, val nickname: String) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T =
        modelClass.getConstructor(String::class.java, String::class.java)
            .newInstance(mode, nickname)
}

class MyViewModel(val mode: String, val nickname: String) : ViewModel()