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

Ali*_*lin 1 android mvvm viewmodel android-viewmodel

我看过很多教程,但并没有真正让自己正确理解如何处理 MVVM 中的某些情况。

假设有一个从DAO使用的a 获取数据的存储库Room

class Repository(){

  fun getItems() = itemsDAO.getItems()

}
Run Code Online (Sandbox Code Playgroud)

查询 Repository 的 ViewModel

class FragmentViewModel:ViewModel(){

    val items = repository.getItems()

    fun updateItem(Item item){
       repository.updateImte(itemm)
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个片段

class MyFragment:Fragment(){

   //onViewCreated
   viewModel.items.observe(...){
        //if result, update the views
     }

  buttonUpdateItem.setOnClickListener{
    viewModel.updateItem(Item item)    
  }

}
Run Code Online (Sandbox Code Playgroud)

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

一种。鉴于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)
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

湾 应该如何ViewModel处理Fragment交互,更精确地处理按钮单击事件?应该fragment像上面的示例一样,调用viewModel.updateItem函数还是viewModel应该返回一个onClickListener应该设置为按钮的变量?

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

d. 正如您所看到的,例如,如果我想更新一个项目,那么ViewModelHold 变量LiveData<List<>>fragment传递该Item. 这是一个好方法吗?

小智 5

首先,我想向您指出 GitHub 上的Android 架构蓝图

该项目的重点是演示如何构建代码、设计架构,以及采用这些模式对测试和维护应用程序的最终影响。您可以通过多种不同方式使用此处演示的技术来构建应用程序。您自己的特定优先级将影响您在这些项目中实现概念的方式,因此您不应将这些示例视为规范示例。

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

一种。您更新的版本是执行此操作的正确方法 - 检索项目列表,调用存储库方法一次并将返回值存储在ViewModel. 使用LiveData<List<Item>>在你的DAO一个返回值和房间会自动通知你ObserverFragment任何变化。

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

C。您只需要在ViewModel. 例如,当您将 id 额外参数传递给Fragmenta 时Bundle,您将ViewModel使用此 id初始化以加载该项目。

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

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