MVVM架构优化

前言

关于MVVM优秀的架构,目前市面上有挺多:例如:MVVMHabit , Jetpack-MVVM-Best-Practice ,其中MVVMHabit主要是针对ViewModel的能力的扩充,Jetpack-MVVM-Best-Practice 主要是以Clean Architecture设计思想为基础的层次划分;但是都没有涉及到特别复杂页面的架构设计,例如在页面特别复杂的情况下,ViewModel的代码量将是巨量,如何解决这类问题?


1.MVVMHabit

MVVMHabit架构.png


ViewModelxxx
所有的ViewModel实现类,其中包含了ViewModel的本职工作(google赋予它的能力),也就是视图相关的状态托管及管理

BaseViewModel
在ViewModel的本职工作之外扩充了它的能力showDialog,startActivity等(主要是通过LiveData分发数据,让监听LiveData的BaseActivity处理具体事务);UIChangeLiveData uc 这个是统一管理上述LiveData

IBaseViewModel
自定义的LifecycleObserver观察者,在对应方法上用注解声明想要观察的宿主的生命周期事件,在宿主中addObserver后即可接受宿主分发的相应事件。也即跟宿主生命周期有了个绑定。

Lifecycle
Lifecycle 是具备宿主生命周期感知能力的组件。它能持有组件(如 Activity 或 Fragment)生命周期状态的信息,并且允许其他观察者监听宿主的状态。它也是 Jetpack 组件库的的核心基础。

再也不用手动分发宿主生命周期,在也不用手动反注册了。

1.jpg

具体Lifecycle的实现原理,文章后面有补充,因为不在主流程中,就不在这块占地方了。

BaseActvity
作为宿主持有viewModel,让viewModel感应宿主生命周期;监听viewModel中liveData的回调,处理startActivity等操作

Actvityxxx
用于初始化viewModel及initVariableId()

MVVMHabit总结

MVVMHabit架构流程.png

ViewModel跟视图(Activity/Fragment)一一对应的关系,通过对ViewModel的能力扩充,使其有自己的生命周期管理及各种能力;承担了原来视图中的数据请求,业务逻辑及视图状态托管(liveData)的工作。



2.改造ViewModel

复杂的页面(十多个接口的数据获取及拆开的十几个xml中的交互),对单ViewModel绝对不太友好(成千上万行代码),所以ViewModel的改造势在必行,造成ViewModel臃肿的主要原因是"能力越强责任越大",也就是给ViewModel扩充的能力太多导致,有两种减压方案:

  • 职能的拆分
  • 拆多ViewModel

2.1职能的拆分

回到ViewModel的本职工作:

ViewModel 的本职工作是 状态托管 和 状态管理 ,其中状态数据变化时驱动视图的改变。所谓数据驱动,本质上不过是编译时注解自动生成的、以适配器模式来运筹帷幄、以观察者模式 来监听和通知视图改变状态。

ok,说的直白点,ViewModel中仅仅用来放置LiveData就好了,这就是系统给他的工作,当然了,如果是比较简单的页面,让ViewModel承担别的责任也无可厚非,因为官网也没制止这种行为。

现在问题来了,既然ViewModel不做这些工作,那要谁来做?嗯,是时候祭出我们的软件行业的镇宅图了。

Clean architecture

clean.jpeg

这种看起来像“洋葱”的环形图就是Clean Architecture,不同颜色的“环”代表了不同的系统结构,它们组成了整个系统,箭头则代表了依赖关系

分层

  • 外层:实现层
  • 中间层:接口适配层
  • 内层:业务逻辑层

实现层
一句话:实现层就是Android框架层,包括Android的东西,与平台特性相关,例如:Activity的跳转,开启Service等。

接口适配层
接口适配层的目的是连接业务逻辑与框架特定代码,担任外层与内层之间的桥梁。例如Presenters,Controllers

业务逻辑层
这一层解决所有的业务逻辑,不包含Android平台的任何代码,可以单独提出来测试,在我们做平台化的时候,这一层的一些UseCase(一个Request可以理解为一个UseCase)也可以被共用,拆分的力度会细些

实现方案
有了上述理论的支持,对ViewModel职能拆分后的设计如下:

单ViewModel架构.png

补充
实际上的Clean architecture设计思想还涉及到内外环的依赖规则及抽象原则,外圈跟内圈的交互都是通过接口,这就需要依赖注入,引入Dagger,但我不太喜欢在此种场景引入Dagger,从而带来额外的性能消耗,提升普及难度。


2.多ViewModel

按照1职能的拆分,我们已经能开开心心的设计代码了,但还是会很遗憾的发现,ViewModel中存放的LiveData及各种交互还是会很庞大,这就需要拆ViewModel,那么ViewModel的拆分规则是啥???有两种方案:

  • 对应不同的xml拆不同的ViewModel
  • 对应不同的Request拆不同的ViewModel

对应不同的xml拆不同的ViewModel
ViewModel的本职工作就是对视图的状态托管及管理,那么根据视图中拆分的xml规则来拆分viewModel没毛病。但是会有以下几个问题:

  • 产品的心如女人难以琢磨,哪天来个UI调整....
  • 多App复用性,假如你公司有几款产品,UI不一致导致ViewModel的复用性差

对应不同的Request拆不同的ViewModel
这是目前我采用的拆分方案,让ViewModel跟xml完全解耦,再也不怕产品改需求了,复用性也得到提升,修改后的整体方案如下:

架构图总览.png

  1. UI层通过DetailPresenter持有的各种Request发送数据请求,发送的先后顺序由DetailPresenter自己控制。
  2. Domain层中Request中发起网络请求,获取结果后(如果需要的话可以做一些数据的转换),并透过LiveData分发回DetailPresenter中的订阅者。
  3. DetailPresenter中数据回来后,可以把数据设置给相对应的ViewModel中,ViewModel在驱动相应的视图更新数据。


3.补充

Lifecycle架构组件原理

你可能感兴趣的:(MVVM架构优化)