Android 应该如何架构 MVP,MVVM ,MVI ?

823 阅读5分钟

结论

没有最好,只有最适合,结合自身情况,做最适合的选择。 Jetpack 现在是Google主要推荐的方向,目前Google推进Android向MVVM 发展。 MVI我认为更加严格的MVVM,甚至都不能说是MVVM的变种,因为他的逻辑就是MVVM

分析 MVP

MVP 是前些年 一直特别流行的架构,当时出来的时候很多人问我,说现在MVP这么火,他到底是个什么东西??

MVP 当时最重要的作用,就是职责分离,以前所有的逻辑都写Activity/Fragment里面了,那么现在把View 单独出来,把业务逻辑单独出来 这样每个业务都会非常清晰了,但是因为Activity/Fragment本身就可以作为View ,所以 你可以把Activity/Fragment作为View使用,也可以单独创建一个View层。只是简单的说说这个意思。不过具体使用可能还是复杂一些,还需要各种封装。

但是MVP 需要很多模板代码,虽然可以通过封装减少,但是整体 还是感觉,类相对比较多。

分析 MVVM

MVVM  跟 MVP 很相似,但是又有一些不同。

MVVM  跟 MVP的区别? 有一个 是  P 持有 View 而 VM 是不持有View 的。

这样有什么好处?就是ViewModel 层不持有View ?只是解耦么?

下面说的VM 不是Android ViewModel 类 而是架构上VM 层 。区别很大不是一个东西。

当然解耦是他的一个作用,但是却不能说是他的优势。如果是为了解耦而解耦,那就没有意义了,反而解耦之后引出来很多新问题,比如粘性事件。这个还真是由于解耦带来的新问题,虽然你可以用 SingleLiveEvent 适当的解决问题。但是终究没有MVP直接持有来的方便。从这开始又有很多人想出了一个新的模式叫MVI。后面会说。

既然,解耦不方便还带来了很多新问题,那么为什么还要用MVVM,这么看的话MVP可能更适合。从很多场景出发,确实不能说MVVM 一定比MVP 更好。但是 MVVM 的优点才是我们选择MVVM 的主要原因。

MVVM 一个重要特性

VM 层 不依赖Activity/Fragment 。甚至ViewModel层完全可以不依赖任何的Android特性。这样带来的最大好处是VM 层 的逻辑更加清晰,维护起来更加方便。数据处理变得更加简洁高效。就像横竖屏切换对VM 层没有影响。因为VM 本来就是只负责业务逻辑 不用考虑任何的 页面逻辑,因为VM 和 V 的解耦才可以带来这样的优势。这个才是MVVM 的核心。至于 Android ViewModel 类 其实 可以理解为MVVM 实现的一种 支持。更类似的DataBinding。只是 为了实现MVVM 的一种尝试。用的好,会节省很多代码。但是不用也完全可以自己实现MVVM.

分析 MVI !!! MVI 难道不是MVVM 么?

我的结论MVI就是MVVM。由于MVVM中 VM 与 V 的解耦,VM 不能直接调用 V 的方法。而只能修改数据,然后V 监听数据变化做出响应。而 粘性问题 就是这里遇到的第一个问题。如果是数据这样做就没有问题。但是如果是事件呢?比如我发一个Toast,获取弹一个Dialog 。SingleLiveEvent是一个选择。但是它还是通过LiveData进行通讯的。而LiveData就要区分 什么是事件,什么是数据,其实并不符合LiveData 作用,只是,没有太好的办法。不管怎么封装。其实说白了都是需要数据通信。

这样有什么问题?总结起来就是,页面显示其实跟数据内容并不一致,而MVI就是想从数据驱动的方式解决上述粘性问题,页面显示只根据数据内容,只要数据变化页面就变化。这样的好处就是行为,和内容一致。但是整体还是沿袭了MVVM的架构,只是在显示的时候不会发送事件了,只是在VM 层修改数据。而这些逻辑都是在VM 层完成的。

MVI 到底是什么

我更愿意叫它严格的MVVM,MVVM 本身就是解耦VM 和V 。只是在使用中,我们没有确保,状态和 内容一致,而MVI的模式就是 确保V 的显示,永远只基于VM 的内容。而这个本身就是MVVM 要做的事。只是更加严格了,如果不严格的去做,我们也姑且叫他MVVM吧。不管怎么样,MVI 也需要做很多复杂的封装,写起来并不会比MVVM简单。但是最大的优势就是,不区分事件和 数据。保证了数据一致性。

总结

MVP,MVVM ,MVI,各有优势。并不能完全说谁一定好,根据自身情况,做最适合的最重要。

MVI 更像是一种 严格的 MVVM,我更愿意叫MVI 为MVVM。

Google 目前的主流推广架构就是MVVM。所以,如果新项目可以尽量用MVVM或许是个更好的选择。

DataBinding 用好了是个非常优秀的方案,但是用不好就很鸡肋。可以考虑更加轻量的ViewBinding

DataBinding 不是MVVM 也不是MVVM 标配。更像是一种早期实验性的MVVM实现方案,很好很强大。用的好,继续用

现在Google主推Kotlin。毕竟Java的版权问题是个问题,但是Kotlin的新特性确实是更值得期待。

Android Kotlin Flow + 协程 + Retrofit + MVVM 目前是一个不错的方案,非常推荐大家直接使用。