Mvvm模式: Databinding 与 ViewModel+LiveData+Repository(下篇)

阿凡达2018-07-20 13:48

Databinding的缺点:

综上我们介绍了Mvvm模式的优点,databinding是实现Mvvm模式的一种数据绑定框架,自然拥有上述优点,那么databinding有哪些缺点呢?

1、databinding的View层UI显示是在xml文件中实现的,当出现问题时,无法确定是Model的问题还是xml的问题,而且xml中也不方便调试。 2、基于数据驱动的databinding ,在比较大的模块时,Model层数据可能会比较大。而且在释放的时候不能像其他模式一样,不同View的数据无法根据各自View的生命周期来进行释放,而是在整个页面销毁时统一释放,这样就会占用更大内存。 3、View的复用。我们在项目中经常用到View的复用。而在databinding中 View在布局文件中可以绑定不同的model,在复用时除了要考虑View的复用之外,还需要考虑model的问题。 4、当然还有一个缺点。对于做前端开发的开发者来说,在布局文件中写对应的绑定数据和事件的逻辑是很正常的操作,但是对于移动开发者而言,这会是一个全新的体验,也许有人就无法接受这种情况。

Android Architecture Components Android Architecture Components官方文档

那么使用ViewModel+LiveData+Repository 如何构建一个MVVM模式的项目呢?

下图为各模块关系图:

View层:

View层由Activity/Fragment/自定义View组成。在View层中,View不做具体的数据和逻辑处理操作,View层只会将数据和事件操作和ViewModel进行绑定。View 监听数据的变化,当ViewModel中的LiveData数据发生变化时,进行Ui的更新操作。同时,View层将事件绑定以命令的方式交给ViewModel去处理。总之,View层只做UI相关操作,逻辑处理数据获取等交给ViewModel。

ViewModel:

ViewModel是逻辑处理类,负责数据处理和View层与Model层的交互。ViewModel通过数据仓库Repository获取数据来源,处理来自View的事件命令,同时更新数据。

Repository:

数据仓库: 一个数据仓库负责获取同类型的数据来源。比如图书数据仓库能够获取各种条件筛选的图书数据,这份数据可以来自网络(Retrofit + OKHttp),本地Database(Room),缓存 (HashMap)等等,ViewModel在从Repository获取数据时,不需关注数据具体是怎么来的。

Model :

因为有了Repository的概念,所以这里的Model的定义相对简单,就是JavaBean,即网络请求对应的实体数据。

ViewModel的组成:

1、Context:

ViewModel因为需要通过Repository来异步获取相关数据,持有Context可以在异步请求结束时,判断Context是否已经销毁来决定是否取消回调。而ViewModel需要处理逻辑,一些工具类本身也需要Context。

2、Data Field 数据绑定(Observable Model):

在Databinding中,ViewModel会持有ObservableField等的数据,View监听ObservableField的数据变化,而当ViewModel中ObservableField数据变化时即会通知UI进行相应更新。在不使用databinding时,就可以通过LiveData起到相同的作用。

3、事件绑定:

View层的一些事件,比如onClick事件,OnRefresh事件等等,在事件触发时,通过ReplyCommand的方式,将事件传递给ViewModel层进行对应的逻辑操作。

事件绑定操作通过RxJava来实现。相对于使用Listener来说,使用RxJava更便捷,而且不会出现Listener回调方法中可能会返回View的引用。这样的话,就无法避免在ViewsModel中使用View的引用直接操作UI的问题。



4、数据仓库:

数据仓库负责获取数据来源。比如网络请求,数据库请求,本地文件等的数据的获取通过Repository来得到。

5、Model :

这里的model即为所需数据对应实体,不包含获取数据的接口方法和实现等。获取数据交给Repository,处理数据交给ViewModel。

6、childViewModel:

在一些情况下,ViewModel会持有childViewModel。比如Activity中嵌套Fragment,Activty对应ViewModel,而Fragment也有一个ViewModel。那么Activity的ViewModel是可以持有FragmentViewModelde 引用的。

如下为一个ViewModel的部分代码实现:

ViewModel中主要通过Repository来获取数据,并根据View层传递过来的事件指令操作数据,数据发生改变后,View层监听到变化并更新UI。通过这种方式,完成双向绑定和MVVM的设计流程。

关于ViewModel和Repository管理的相关设计类图如下:

ViewModelManger : 主要是对ViewModel的生命周期进行管理,一个CustomContext对应一个BaseViewModel,而一个CustomContext同时对应一个Activity/Fragment/View的生命周期。当View层生命周期结束时,就将Map中指定Key的BaseViewModel移除,并调用其onDestroy方法来完成相应数据销毁工作。

BaseRepository:数据仓库实现类。主要用于获取数据,包括但不限于网络数据,数据库,本地文件等等的数据来源。

BaseViewModel : 每个Activity/Fragment/View 对应一个BaseViewModel。从BaseRepository获取数据并根据View层Command事件处理数据并改变数据的值。用于View层和 Repository Model的交互以及数据逻辑的处理。

和Databinding相比,其优点在于:

1、Mvvm模式的优点其都具备。 2、Databinding不便于调试,而ViewModel+LiveData因为其双向绑定的操作都在Activity/Fragment/View中进行,不会出现像在xml中不便调试的问题。 3、会对ViewModel进行统一管理,在页面销毁时,销毁对应的ViewModel以避免造成内存占用。 4、还有一点,对于移动开发者而言,可能更易接受这种Mvvm模式的绑定方式,而不是在布局文件中直接进 行数据和事件的绑定操作。

本文通过对比几种不同的设计模式,并详细介绍了MVVM模式的两种实现方式,供大家了解和参考。不同的设计模式会有各自的优缺点,不同的项目应该按照各自的实际情况和使用体验来进行对应的设计。在选择的过程中需要考虑诸多问题,比如性能问题,使用便捷程度,单元测试,是否相互独立等。当然还有一点很重要的就是,共同开发的同事是否认同并喜欢这种开发方式,毕竟这会影响到他们的开发流程,习惯和体验。如何说服他们认可这种设计模式,就需要你提供便捷和健壮的封装框架,使他们很爽很开心很便捷地使用这种设计模式,并且能够满足项目代码的可扩展性,解耦和相关独立。做到这些,就能满足调用者,项目代码健壮性,模块独立性和可扩展性的需要了。

2、MVC,MVP 和 MVVM 的图示

3、如何构建Android MVVM应用程序

相关阅读:

Mvvm模式: Databinding 与 ViewModel+LiveData+Repository(上篇)

本文来自网易实践者社区,经作者朱强龙授权发布。