最近看到了几篇与 Jetpack MVVM 有关到文章,使我不禁也想淌一下这场混水。我是在 2017 年下半年接触的 Jetpack 的那套开发工具,并且后来一直将其作为开发的主要框架。在这段时间的使用过程中,我踩过一些坑,也积累了一些经验,为了将其推广到其它到项目中又专门封装出了一个库。当然,Jetpack 所提供的组件已经比较完善,我的工作只能算是锦上添花。下面我就介绍下,现在我是如何在项目中使用 Jetpack MVVM 的。
1、后起之秀和黯然失色的 MVP
MVP 非常强大,也是或者曾经是很多大公司首选的开发框架。但是相比于如今的 MVVM,曾经的 MVP 模式在使用起来存在诸多的不便,难免显得黯然失色。
首当其冲的是,在使用 MVP 编写客户端代码的时候你要写大量的接口和类。一般的 MVP 模式中,我们需要先通过接口定义 Model、View 和 Presenter 要实现的方法;然后,需要再编写三个类来实现以上三个接口的逻辑。就是说,一般的,为了实现一个界面的逻辑,你需要编写至少六个类文件。
其次,Presenter 比较臃肿。Presenter 负责 View 和 Model 层之间的交互,请求的结果及其与 View 层的交互逻辑都在 Presenter 中完成。很多框架中,为了解决 View 和 Model 层之间的强引用关系,在 Presenter 定义 Handler 来通过消息的方式传递信息。这就使得代码的过于模版化,增加了很多与具体业务逻辑无关的代码。此外,如果使用 Handler 作为消息传递的桥梁,因为通过更新 UI 又发生在主线程里面,就可能会导致主线程消息堆积过多。
那 MVVM 是如何做的呢?下面的这张图大致地诠释了 Jetpack MVVM。实际上,Jetpack 所提供的 MVVM 核心的功能只有 ViewModel 和 LiveData 两个。ViewModel 主要用来通过 Model 请求数据信息,然后通过 LiveData 作为信息交互的桥梁,将信息传递给 View 层。从类的数量的角度上来看,使用 MVVM 实现一个页面,你只需要写三个类文件。
![](https://i-blog.csdnimg.cn/blog_migrate/9b43e262ebeed79ad72c024c9c5c5297.png)
而作为 ViewModel 和 View 层交互的中介的 LiveData 呢?你只需要将它看作一个普通的变量就可以了。它内部缓存了我们的数据。它会在你修改这个数据的时候通知所有的观察者数据的变更。所以,LiveData 不存在 Handler 那样是消息拥堵的问题。
此外,使用 LiveData 还可以解决页面频繁刷新以及刷新的时机的问题。比如,一个处于后台的页面通过 EventBus 监听数据变化之后会先被保留到 LiveData,然后当页面回到前台的时候再一次性刷新 UI。这样就避免了处于后台的页面多次刷新 UI 又控制了刷新的时机。
如果你不熟悉 MVP、MVVM 等架构模式,或者你想知道 LiveData 和 ViewModel 的实现原理,可以参考我之前的相关的文章:
2、Jetpack MVVM 的项目实践
Jetpack 提供的 MVVM 已经足够强大,很多人会认为没有必要在其基础之上做进一步封装。正因如此,使得 MVVM 在实际应用过程中呈现出了许多千奇百怪的姿态。比如,MVVM 和 MVP 杂糅在一起,ViewModel 和 View 层混乱的数据交互格式,ViewModel 中罗列出一堆的 LiveData 等等。实际上,通过简单地封装,我们可以更好地在项目中推广和应用 MVVM。我开发 Android-VMLib 这个框架的目的也正在于此。
2.1 拒绝大杂烩,一个 Clean 的 MVVM 框架
首先,作为一个 MVVM 的框架,Android-VMLib 所做的东西并不多,我并没有将其与各种网络框架等整合在一起,可以说得上是非常干净的一个框架。截至目前它的依赖关系如下,
![](https://i-blog.csdnimg.cn/blog_migrate/c52e24d61a2e44d89422196352e95b5c.png)
也就是说,除了我的编写的图片压缩库 Compressor 以及一个工具类库 Android-utils 之外,引入它并不会为你的项目引入更多的库。对于 EventBus,除了我们在项目中提供的一个封装之外,也不会为你引入任何类库。至于友盟,我们只不过是为你在顶层的 View 层里注入了一些事件追踪方法,也不会强迫你在项目中添加友盟依赖。也就是说,除了那两个必选的库之外,其它都是可选的。该框架的主要目的是赋能,是不是要在项目中应用完全取决于用户。
好了,接下来就详细介绍下这个类库以及正确的使用 MVVM 的姿势。
2.2 MVVM 和 Databinding 的暧昧关系
说到 MVVM,总是绕不开 Databinding. 我之前也了解过许多 MVVM 框架,很多都将 Databinding 作为了项目必需的方案。事实上,MVVM 和 Databinding 之间没有半毛钱的关系。
Databinding 提供了双向的绑定功能,因此很多框架直接将 ViewModel 注入到了 xml 里面。我个人是比较反感这种做法的。或许是早起 Databinding 不成熟的时候经常带来莫名其妙的编译错误 xxx.BR not found
以及 can't find