我看过很多教程,但并没有真正理解如何在MVVM中处理某些情况。
假设有一个存储库从使用Room
的DAO
中获取数据
class Repository(){
fun getItems() = itemsDAO.getItems()
}
查询存储库的ViewModel
class FragmentViewModel:ViewModel(){
val items = repository.getItems()
fun updateItem(Item item){
repository.updateImte(itemm)
}
}
和一个片段
class MyFragment:Fragment(){
//onViewCreated
viewModel.items.observe(...){
//if result, update the views
}
buttonUpdateItem.setOnClickListener{
viewModel.updateItem(Item item)
}
}
这是我从教程中了解到的方法。基本上我有一些事情需要澄清,我想请求你的帮助。
a。考虑到ViewModel
的这种实现,如果用户旋转设备并重新创建片段,这不意味着在添加observe
时将再次查询数据库吗?我正在考虑像这样的ViewModel的更新版本
class FragmentViewModel:ViewModel(){
private final var itemsObservable;
init {
itemsObservable = repository.getItems()
}
fun items(){
return itemsObservable
}
fun updateItem(Item item){
repository.updateImte(item)
}
}
如果我是对的,这应该允许从db返回初始值,而不是在片段重新创建的情况下再次调用db。
b。ViewModel
应该如何作用于Fragment
交互,更确切地说是按钮点击事件?fragment
应该像上面的示例一样调用viewModel.updateItem
函数,还是viewModel
应该返回一个onClickListener
变量,该变量应该设置为按钮?
c。传递给fragment
的参数是否也应添加到ViewModel
?
d。正如您所看到的,ViewModel
保存了LiveData<List<>>
的变量,因此,例如,如果我想更新一个项目,那么fragment
会传递该Item
。这是一个好方法吗?
首先我想指出GitHub上的Android架构蓝图:
本项目的重点是演示如何构建代码,设计您的体系结构,以及采用的最终影响测试和维护应用程序的这些模式。您可以使用这里展示了许多不同的构建应用程序的方法。您自己的特定优先级将影响您如何实施这些项目中的概念,所以您不应该考虑这些示例成为规范的例子。
这些是Android中不同架构的官方示例,您绝对应该将其作为自己项目的灵感来源。
a。更新后的版本是正确的方法——检索项目列表,调用存储库方法一次,并将返回值存储在ViewModel
中。在DAO中使用LiveData<List<Item>>
作为返回值,Room将自动通知Fragment
中的Observer
任何更改。
b。CCD_ 21可以具有CCD_。onClickListener
应放置在Fragment
中。在调用updateItem
方法之前,您可能还需要在Fragment
中进行一些验证。同样重要的是,不要在ViewModel
中保留任何View
引用
要将更新状态通知Fragment
,您可以考虑在ViewModel
中设置另一个LiveData
字段(例如errorMessage: LiveData<Int>
(,并为其分配要显示的字符串资源的R. id
。通过这种方式,您可以将确定要显示的特定消息的逻辑从Fragment
移动到ViewModel
。
c。您只需要ViewModel
中的一些参数。例如,当您在Bundle
中向Fragment
传递了一个id额外参数时,您将使用该id初始化ViewModel
以加载该项。
d。通过Item
肯定是一个不错的方法。您还可以考虑创建一个Presenter,将某些逻辑从Fragment
中分离出来(这样它就不能和Item
一起使用了(。您可以在上面的GitHub链接中找到更多信息和示例。
因此,我认为根据您正在开发的应用程序,有不同的方法可供选择。测试是非常重要的,在实现一种方法后,你会发现它如何影响编写测试的容易性。但这就是我对你问题答案的看法。