【问题标题】:Handle data in ViewModel and Fragment in MVVM处理 ViewModel 中的数据和 MVVM 中的 Fragment
【发布时间】:2018-07-17 12:50:15
【问题描述】:

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

假设有一个存储库从使用RoomDAO 获取数据

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)
        }
    }

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

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

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

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

【问题讨论】:

    标签: android mvvm viewmodel android-viewmodel


    【解决方案1】:

    首先我想指出你 GitHub 上的Android Architecture Blueprints

    本项目的重点是演示如何构建您的 代码、设计架构以及采用的最终影响 这些模式用于测试和维护您的应用程序。您可以使用 此处以多种不同方式演示的技术来构建应用程序。 您自己的特定优先事项将影响您如何实施 这些项目中的概念,因此您不应考虑这些示例 成为典型的例子。

    这些是 Android 中不同架构的官方示例,您绝对应该将其作为您自己项目的灵感来源。

    一个。您的更新版本是执行此操作的正确方法 - 检索项目列表,调用存储库方法一次并将返回值存储在 ViewModel 中。在你的 DAO 中使用LiveData<List<Item>> 作为返回值,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 中的一些参数。例如,当您将一个 id 额外参数传递给 Bundle 中的 Fragment 时,您将使用此 id 初始化 ViewModel 以加载项目。

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

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

    【讨论】:

    • 很棒的答案。感谢您的宝贵时间和详细信息。
    • @Alin 没问题,乐于助人!
    • 这里有一些关于使用 Init 的 ViewModel 的有趣之处。在 Android Studio 中,如果我使用 init,我会收到变量“可以与赋值连接”的建议,所以如果我应用它,它会以与以前相同的结尾...
    • 对,在这个简单的情况下,如果repository字段已经初始化,你仍然可以加入它,你仍然只执行一次repository方法。但也许您想使用依赖注入并在构造函数中注入存储库。然后你需要在那里初始化items 字段。所以底线是你只想分配一次。
    猜你喜欢
    • 2017-03-22
    • 2018-10-14
    • 1970-01-01
    • 2014-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多