Android全新架构-MVI

444 阅读4分钟

一、MVI架构是什么

MVIMVVM 很相似,其更加强调数据的单向流动和唯一数据源。

定义分为以下部分:

  1. Model:UI状态,例如页面加载状态、控件位置等都是一种状态。
  2. View:View,可能以Android View(Activity、Fragment)或者Compose形式呈现。View中所有变化,都通过观察Model的变化实现
  3. Intent:用户意图,用户通过点击、滑动等在View上动作产生的各种操作,被包装成意图,单向传递给Model。

MVI中的具体层级:

image.png

其中的ViewState就是与MVVM产生差别的部分。

MVVM中,UI与数据是进行了双向绑定的,而MVI中,所有用户操作被定义成了单向流。所有UI变化只有从ViewModel中订阅才可以感知。

二、MVI的作用

MVI架构是在前身MVVM基础上的优化升级版,其最大的变化就是单向数据流,所有的用户意图只由ViewModel接收并处理,所有的UI变化只由ViewModel传递的UiState决定。流向更纯粹,解耦更清晰。

同时MVI将MVVM使用的LiveData进行了优化,用StateFlow取代,将所有UI与数据变化集中在了Model层。

三、具体分层

MVI架构分为3层:界面层、网域层、数据层

具体层级:

image.png

UI Layer(界面层)

界面的作用是在屏幕上显示应用数据,并充当主要的用户互动点。每当数据发生变化时,无论是因为用户互动(例如按了某个按钮),还是因为外部输入(例如网络响应),界面都应随之更新,以反映这些变化。实际上,界面是从数据层获取的应用状态的直观呈现。

Domain Layer(网域层)

UseCase

作用

网域层负责封装复杂的业务逻辑,或者由多个 ViewModel 重复使用的简单业务逻辑。此层是可选的,因为并非所有应用都有这类需求。因此,您应仅在需要时使用该层,例如处理复杂逻辑或支持可重用性。

网域层具有以下优势:

  • 避免代码重复。
  • 改善使用网域层类的类的可读性。
  • 改善应用的可测试性。
  • 让您能够划分好职责,从而避免出现大型类。

Data Layer(数据层)

Repositories和Data Sources的层级

Repo中包含network与Database数据源

数据层由多个存储库组成,其中每个存储库都可以包含零到多个数据源。您应该为应用中处理的每种不同类型的数据分别创建一个存储库类。例如,您可以为与电影相关的数据创建一个 MoviesRepository 类,或者为与付款相关的数据创建一个 PaymentsRepository 类。

命名惯例

数据类型 + Repository。

例如:NewsRepositoryMoviesRepositoryPaymentsRepository

Demo样例

Demo中的目录结构

image.png demo项目在根目录下分了4个文件夹:data、domain、ui,以及用于将除界面意外所有内容注入APP的依赖注入框架koin(官方推荐使用Hilt,但个人觉得相比如全是注解的Hilt,Koin更简洁更优雅)

UI层

image.png

UI层分为4个文件夹:

  • adapter。RecyclerView等的适配器
  • ui。View或Compose的界面
  • uistate。直接关联对应界面的界面状态
  • viewmodel。处理界面与界面状态交互状态容器

Ui

展示Ui,传递用户意图。

image.png

UiState

Ui层与Model层沟通的模型。

image.png

ViewModel

其中是负责响应用户的操作,并与数据层或网域层沟通,得到结果后通过stateFlow将结果反馈给UI层。

image.png

网域层

网域层内只包含一层,内部都是封装着复杂业务逻辑的UseCase

image.png

UseCase中的内容

UseCase类的入参是Repository与其他UseCase。用于封装业务逻辑。

image.png

数据层

image.png

数据层分为repository和source两个文件夹:

  1. repository。对外暴露的local与remote中最简化元操作。

  2. source。所有数据来源,仅对Repository可见

    1. local。本地数据,demo中使用的是Room

      1. bean。封装的业务模型
      2. dao。Room所需的Dao文件用于具体的CURD操作
      3. db。定义的DB接口及DB接口的实现,仅暴露repository中所需要的元操作
    2. remote。远程数据,用于网络请求,demo未找到合适接口,暂不举例

Repository

对外暴露的local与remote中最简化元操作。

image.png

image.png

Source

bean。封装的业务模型

image.png

dao。Room所需的Dao文件用于具体的CURD操作

image.png

db。定义的DB接口及实现,仅暴露repository中所需要的元操作

image.png

image.png

四、注意

MVI也有很多缺点,例如每次更新UI都会新建UIState的新对象,这也是开销。

所有的架构都是为项目服务的,请根据自身项目情况选择最适合的架构。

五、参考资料

应用架构指南 | Android 开发者 | Android Developers (google.cn)