4

通过示例,我看到了 2 种使用 Android 架构组件的 MVVM 方法。

第一种方法:

  1. ViewModel提供LiveData
  2. Activity订阅LiveData
  3. 当被调用的观察者Activity将数据设置为ViewModel ObservableField.
  4. 整体ViewModel传递给绑定。
  5. xml你只是设置ObservableField为值

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        app:visibleGone="@{viewmodel.listLoading}"/>
    
    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swiperefresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:refreshing="@{viewmodel.listRefreshing}"
        app:onRefreshListener="@{() -> viewmodel.refreshList()}"
        app:visibleGone="@{!viewmodel.listLoading}">
    

优点:我不需要传递状态(例如“加载”),因为我更新listLoading ObservableField如下ViewModel

val listLoading = ObservableBoolean(false)
/** other observable fields go here **/

val list: MutableLiveData<List<Item>> = MutableLiveData()

  fun loadList() {
        listLoading.set(true)
        repo.getList { items ->
            list.value = items
            listLoading.set(false)
        }
    }

缺点:这种方法有什么缺点吗?

第二种方法:

  1. ViewModel提供LiveData
  2. Activity订阅LiveData
  3. 当被调用的观察者Activity被传递给绑定时
  4. 只有需要的对象(pojo)被传递给绑定

优点:这种方法有什么优点吗?

缺点:状态应该从ViewModel. 在这个来自 Google 的示例中,数据被包装在Resource对象中。

第一种方法用于Google 的另一个示例应用程序

我想从有更多使用 Android 数据绑定和 Android Arch 组件经验的开发人员那里了解这两种模式的优缺点。

4

1 回答 1

6

您应该考虑将视图逻辑与业务逻辑分开。

由于您有一个使用数据绑定和 AAC 来处理的 ViewModel,因此您还应该分离视图(布局)内的逻辑。

只需将两个变量传递给您的布局。一个是处理业务逻辑的 VievModel,比如按下按钮和处理逻辑,第二个是视图(片段)。

之后你可以使用

app:onRefreshListener="@{() -> yourViewFragment.refreshList()}"

如果当前没有订阅视图,请避免出现“上下文泄漏”或无效的解决方案。

由于 onRefreshListener 绑定到片段,因此可以将其传递到片段中。

您不应该在 ViewModel 中创建 LiveData 或 ObservableField 来处理此类操作,因为如果您暂停并恢复片段,您将再次观察 LiveData。这也意味着您将再次获得最后一次交付的数据。

可以在 ViewModel 中使用的示例:

<Textview ... name="@{viewModel.dataOfYourModel}" onClick="@{viewModel.doNetworkCall}" />

黄金法则:每个以 android.* 开头的包/导入都不应该在视图模型中,除了 android.arch.* 组件。

于 2017-10-11T21:29:27.887 回答