在 MVVM 中处理 ViewModel 和 Fragment 中的数据

Handle data in ViewModel and Fragment in MVVM

我看过很多教程,但并没有真正让自己正确理解如何处理 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)    
  }

}

这是我从教程中了解到的方法。基本上我有一些事情要澄清,我想请求你的帮助。

一个。鉴于 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)
        }
    }

如果我是对的,这应该允许 return 来自 db 的初始值,并且在片段重建的情况下不会再次调用 db。

b。 ViewModel 应该如何作用于 Fragment 交互,更精确地作用于按钮点击事件? fragment 是否应该像上面的示例那样调用 viewModel.updateItem 函数,或者 viewModel 应该 return 应该设置为按钮的 onClickListener 变量?

c。传递给 fragment 的参数是否也应该添加到 ViewModel?

d。如您所见,ViewModel 保存 LiveData<List<>> 的变量,例如,如果我想更新一个项目,那么 fragment 传递 Item。这是一个好方法吗?

首先我想向您指出 Android Architecture Blueprints 在 GitHub 上:

The focus of this project is on demonstrating how to structure your code, design your architecture, and the eventual impact of adopting these patterns on testing and maintaining your app. You can use the techniques demonstrated here in many different ways to build apps. Your own particular priorities will impact how you implement the concepts in these projects, so you should not consider these samples to be canonical examples.

这些是 Android 中不同架构的官方示例,您绝对应该检查一下,作为您自己项目的灵感。

一个。您的更新版本是执行此操作的正确方法 - 要检索项目列表,调用存储库方法一次并将 return 值存储在 ViewModel 中。在您的 DAO 中使用 LiveData<List<Item>> 作为 return 值,Room 将自动通知您在 Fragment 中的 Observer 任何更改。

b。 ViewModel 可以有 updateItem(item: Item) 方法。 onClickListener 应放在 Fragment 中。在调用 updateItem 方法之前,您可能还想在 Fragment 中进行一些验证。同样重要的是不要在 ViewModel.
中保留任何 View 引用 要通知 Fragment 关于更新状态,您可以考虑在 ViewModel 中有另一个 LiveData 字段(例如 errorMessage: LiveData<Int>)并将其分配给 R. id您要显示的字符串资源。通过这种方式,您可以将确定要显示的特定消息的逻辑从 Fragment 移动到 ViewModel

c。您只需要 ViewModel 中的一些参数。例如,当您在 Bundle 中将一个 id 额外参数传递给 Fragment 时,您将使用此 id 初始化 ViewModel 以加载项目。

d。通过 Item 绝对是一个好方法。您还可以考虑创建一个 Presenter 来将一些逻辑从 Fragment 中分离出来(因此它不适用于 Item)。您将在上面的 GitHub link 中找到更多信息和示例。

所以我认为根据您正在开发的应用程序,可以选择不同的方法。测试非常重要,在实施一种方法后,您会发现它如何影响编写测试的难易程度。但这就是我看到你的问题的答案。