浏览示例,我看到了 2 种使用 Android 架构组件的 MVVM 方法。
第一种方法:
ViewModel
提供LiveData
Activity
订阅LiveData
- 当被调用的观察者
Activity
将数据设置为ViewModel
ObservableField
时。 - 整个
ViewModel
传递到绑定。 -
在
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}">
优点:我不需要传递状态(例如"加载"),因为我在ViewModel
中更新listLoading
ObservableField
如下:
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)
}
}
缺点:这种方法有什么缺点吗?
第二种方法:
ViewModel
提供LiveData
Activity
订阅LiveData
- 当调用
Activity
的观察者传递给绑定时 - 仅将所需的对象 (pojo) 传递给绑定
优点:这种方法有什么优点吗?
缺点:状态应该从ViewModel
返回。在此示例中,来自 Google 的数据包装在Resource
对象中。
第一种方法用于谷歌的另一个示例应用
我想知道这两种模式的优缺点是什么,这些开发人员在使用 Android 数据绑定和 Android Arch 组件方面拥有更多经验。
您应该考虑将视图逻辑与业务逻辑拆分。
由于您有一个使用数据绑定和 AAC 来处理的 ViewModel,因此您还应该分离视图(布局)内的逻辑。
只需将两个变量传递给布局即可。一个是 VievModel,它处理业务逻辑,如按下按钮和处理逻辑,第二个是视图(片段)。
之后您可以使用
app:onRefreshListener="@{() -> yourViewFragment.refreshList()}"
如果当前没有订阅视图,请避免出现"上下文泄漏"或无法正常工作的解决方案。
由于 onRefreshListener 绑定到片段,因此可以将其传递到片段中。
您需要在 ViewModel 中创建一个 LiveData 或 ObservableField 来处理此类操作,因为如果您暂停并恢复片段,您将再次观察 LiveData。这也意味着您将再次获得最后的数据。
可以在视图模型中使用的示例:
<Textview ... name="@{viewModel.dataOfYourModel}" onClick="@{viewModel.doNetworkCall}" />
黄金法则:每个以 android.* 开头的包/导入都不应该在视图模型中,除了 android.arch.* 组件。