Android Jetpack系列之MVI架构
文章目录
- 写在前面
- MVI vs MVVM
- 新旧架构对比
- 差异1、LiveData < T> 改为Flow< UIState>
- 差异2、View与ViewModel的交互规范
- 总结
- 资料
写在前面
在之前介绍MVVM
的文章中,介绍了常用的MVC、MVP、MVVM
架构及其对MVVM
的封装使用,其中MVVM
的主旨可以理解为数据驱动:Repository
提供数据,ViewModel
中发送数据,UI层
使用的LiveData
订阅数据,当有数据变化时会主动通知UI层
进行刷新。有兴趣的可以去看一下:
1、 Android Jetpack系列之MVVM使用及封装
2、Android Jetpack系列之MVVM使用及封装(续)
那么MVI
又是什么呢?看了一些关于MVI
的文章,大家都称MVI是(Model-View-Intent)
,其中Intent
称为意图(注意这里的Intent
并不是页面跳转时使用的Intent
),MVI本质上是在MVVM
的基础上将View
与ViewModel
之间的数据传递做了统一整合。
google
官方文档中并没有MVI
的说法,而是在之前的MVVM
架构基础上进行了升级,其主旨意思与MVI
很相近,为了保持一致,后续介绍的MVVM
升级版架构统一称之为MVI
架构。
MVI vs MVVM
新旧架构对比
-
旧版
MVVM
架构:
-
新版
MVVM
或者称之为MVI
:
差异1、LiveData < T> 改为Flow< UIState>
关于LiveData
的缺点:
LiveData
的接收只能在主线程;LiveData
发送数据是一次性买卖,不能多次发送;LiveData
发送数据的线程是固定的,不能切换线程,setValue/postValue
本质上都是在主线程上发送的。当需要来回切换线程时,LiveData
就显得无能为力了。
Flow
可以完美解决LiveData遇到的问题,既可以多次从上游发送数据,也可以灵活地切换线程,所以切到Flow是更优解。关于Flow的详细用法,感兴趣的同学可以参见:Android Kotlin之Flow数据流
注:如果项目中还没有切换到Kotlin
,依然可以使用LiveData
来发送数据;如果已经切换到Kotlin
,那么更推荐使用Flow
来发送数据。
还有一点区别,LiveData
在旧版架构中传递的是实体数据,新版架构中通过Flow
发送的统一为UIState
了。关于UIState
,后面在具体示例中再讲解。
差异2、View与ViewModel的交互规范
新版架构中,提出了单向数据流来管理页面状态的概念,即View层
请求ViewModel
的事件会统一在一起,这样数据传递会集中管控,提高代码的可读性及修改的便利性。单向数据流有以下好处:
- 数据一致性。界面只有一个可信来源。
- 可测试性。状态来源是独立的,因此可独立于界面进行测试。
- 可维护性。状态的更改遵循明确定义的模式,即状态更改是用户事件及其数据拉取来源共同作用的结果。
集中管控有个很大的好处:我们在新版架构中,只需要定义为数不多的几个Flow
即可,多个不同请求都可以使用;而使用旧版MVVM
时,如果请求的数据很多,那么相应的,我们需要在ViewModel
中定义很多的LiveData
或者Flow
,如下:
private val _wanFlow = MutableStateFlow<List<WanModel>>(ArrayList())
val mWanFlow = _wanFlow
其中定义一个可变的Flow
,一个不可变的Flow
,可变Flow
是为了数据的变化,而不可变的Flow
是为了防止在View
层中改变Flow
中的数据,从而破坏单向数据传递。
总结
升级版的MVI
架构相比于旧版MVVM
架构,规范性更好,约束性也更强。但是并不是说新版的架构就一定适合你的项目,架构毕竟是一种规范,具体使用还需要见仁见智。
资料
【1】 应用架构指南:https://developer.android.com/jetpack/guide?hl=zh-cn
【2】界面层架构:https://developer.android.com/jetpack/guide/ui-layer?hl=zh-cn#views
【3】界面事件:https://developer.android.com/jetpack/guide/ui-layer/events?hl=zh-cn#views