什么是架构,以及为什么需要架构设计
- 现象:耦合度高
- 问题:类文件冗长,维护不易,扩展困难,复用程度低,难测试
- 目标:易维护,易测试
- 手段:解耦合,关注点分离
- 模式:总结出来的几种通用方法(MVC,MVP,MVVM,MVI)
MVC
Controller与View互相引用, Controller与Model互相引用
- View:xml布局文件
- Model:管理业务数据,如网络请求、数据库
- Controller:即Activity,处理表现层逻辑
优点
- 初步解决Activity代码冗长的问题,将数据从Activity中分离出去
缺点
- Activity里既要处理View、也要处理业务逻辑,职责不清晰
MVP
Presenter与View通过接口间接引用,Presenter与Model互相直接引用
- View: xml布局文件,Activity,Fragment
- Model:管理业务数据,如网络请求、数据库(同MVC)
- Presenter:处理表现逻辑
优点
- 将Activity中分离出业务逻辑代码,使Activity只处理显示层的事务,它的职责更加清晰
缺点
- 双向依赖:View、Presenter两层互相依赖,其中一方如果变动,另一方也必须跟着变
- 内存泄漏:Model、Presenter、View存在链式的引用,如果Model存在耗时操作,处理不当的话会使View层的Activity泄漏。通过弱引用、手动回收可以避免,但增加了工作量和风险点
- 协议接口膨胀:View、Presenter两层通过接口实现互相调用,逻辑复杂会导致接口类迅速增多
MVVM
View观察ViewModel,后者不引用前者,只是作为数据的发送源。ViewModel和Model互相引用
View:Activity 和 Layout XML 文件,与 MVP 中 View 的概念相同;Model:负责管理业务数据逻辑,如网络请求、数据库处理,与 MVP 中 Model 的概念相同;ViewModel:存储视图状态,负责处理表现逻辑,并将数据设置给可观察数据容器。
Lifecycle, LiveData, Databinding, ViewModel组件是 Google 为了帮助我们实现 MVVM 模式提供的架构组件,它们并不是 MVVM 的本质,只是实现上的工具。
LiveData:可观察的数据存储类ViewModel:存储界面相关的数据,这些数据不会在手机旋转等配置改变时丢失Lifecycle:生命周期状态回调Databinding:可以自动同步 UI 和 data,不用再 findviewById()
优点
- 解除ViewModel对View的依赖,降低耦合度
- 防止内存泄漏
缺点
- 多数据流:View与ViewModel交互分散,缺少唯一修改源,不易于追踪和维护
- LiveData膨胀:复杂的页面需要定义多个 MutableLiveData,并且都需要暴露为不可变的 LiveDat
MVI
在View与ViewModel之间,抽象出ViewState的概念,含义是“View当前的显示状态”。一个View只需要关注一个ViewState
View:Activity 和 Layout XML 文件,与 MVVM 中 View 的概念相同;Intent:定义数据操作,是将数据传到 Model 的唯一来源,相比 MVVM 是新的概念;ViewModel:存储视图状态,负责处理表现逻辑,并将 ViewState 设置给可观察数据容器;ViewState:一个数据类,包含页面状态和对应的数据。
优点
- 唯一可信来源:ViewModel
- 单一数据流:View只需要订阅ViewState
- 响应式:通过订阅完成自动刷新View
缺点
- State膨胀:实践中根据需求选择单/多数据流,不必拘泥于单数据流
- 内存开销:ViewState是不可变类,意味着无法通过对象池实现复用
- 局部刷新:整个View由一个ViewState决定,实践中由
Flow#distinctUntilChanged()等技术帮助刷新