Android MVI 架构简介

翻译来自 Medium :
https://medium.com/@soundhar.p03/android-mvi-architecture-230cd30e40b4
大家有时间和精力可以阅读原文,翻译可能不怎么到位,到时候网批评指正。
MVI架构模式

大家好,在本篇博客中,我们就会讨论有关Andorid的MVI设计模式。近些日子有关Andorid架构模式都在逐步进化中。对于我们开发的App中,我们开始面临新的挑战和困难。新的设计模式将会被发现来解决类似的问题。

作为Andorid开发人员,我们已经拥有了MVC、MVP和MVVM作为最流行和熟知的开发模式,但是这些开发模式都是使用命令式编程方法。通过这种方法,大部分面临的挑战都可以得到解决,但是我们依然会面临一些挑战,比如线程安全、应用状态的维持等等问题。通过这种,我们来看看MVI架构模式是什么,它是如何解决这些挑战的,然后如何来开始MVI.

这里,来聊一下需要做的动作.

1. Android设计模式预览

Android Framework层提供了大量的灵活的实现,来让你随心所欲的组织和创建自己的App。
这种自由是很有价值的,但是它也可以导致程序拥有大量的类,不一致的命令方案,同时也将造成架构不匹配或者缺失。

这种类型的失误将会对App的测试、维护、扩展造成很大的不便。所以,大多人就有了传统的Model-View-Controller(MVC)模式,或者Model-View-Presenter(MVP)模式,或者Model-View—ViewModel(MVVM)模式。

2. 列举现存的设计模式

现在架构模式

3. MVI架构模式

MVI表示的是Model-View-Intent.这个模式最近才被引入Android。受到Cycle.js框架的思路影响,是基于单向圆柱流的原理进行工作的。

在这里插入图片描述

Model:不像其它架构模式的Model,在MVI架构中Model表示UI的状态。举个例子,UI可能会存在不同的状态,比如数据加载Data Loading,加载完成Loaded,用户的动作造成数据的改变,错误,用户当前屏幕位置状态等等,每一个状态都被存储到Model对象中。

View: 在MVIView作为接口,可以在Activity或者Fragment中实现。这个接口的意思就是需要有一个容器来接收不同状态并进行展示。它们使用可观察的Intent(这里的Intent并不是传统的Android Intent,这里应该取Intent的本意,意图)来回应用户的动作。

Intent: 这个并不是之前所提到的Android Intent.用户的动作的结果作为输入值传递给Intent。回过来,我们可以说,我们将会发送Models作为输入给Intent,然后通过View加载这些Model的状态。

在这里插入图片描述

4. MVI数据流

我们可以通过下面的图表来理解MVI数据流的走向。

用户接口始终连接View, 我们上面讲过,数据的加载方式是通过Intent将用户的动作作为输入值发送给Model, 然后Model的变使得View展现形式发生改变。

在这里插入图片描述

5. 为什么需要 MVI

你可能会考虑到这个新模式的使用方法,即使我们在Android开发过程中使用了多种架构。
当应用在扩张,未知的功能需要被添加时,没有明确的状态管理,视图(View)的渲染和业务逻辑可能会变得有些混乱。

代码的可扩展性越高,新的想法和更新就可以越灵活。扩展性、灵活性和更易于测试,这就是MVI架构可以为我们提供的优势。

6. MVI 的关键实力

  1. 单向循环的数据流
  2. 易于捕捉和修复bug
  3. 易于代码测试
  4. 在不需要单元测试的情况下,拥有测试整个app全部层级的能力

7. MVI是如何工作的

用户进行的一个动作,将会被转变为一个Intent–> Intent将会是一种状态,作为输入传递给Model–>Model存储状态,并将状态请求发送到View–> ViewModel中加载状态 --> 显示给用户。

如果我们观察到,数据将会从用户开始,并通过Intent到用户结束.不能通过其它的方式。

因此这种叫做单向架构,如果用户做相同的动作,那么就重复相同的循环。因此它是循环的:

在这里插入图片描述

8. MVI的优势

  • 对于架构来说,维护状态不再是那么困难的事情了。它主要做的就是状态维护;
  • 因为数据流是单向的,所以可以很容易的被跟踪和预测;
  • 它确保线程是安全的,因为状态对象是不可变的;
  • 容易进行Debug,当错误发生时,我们可以知道对象的状态;
  • 更加的解耦,每个组件专注自己的业务和逻辑;
  • app的测试将会很容易,我们可以将不同的业务逻辑映射为状态。

9. MVI的劣势

  • 每一个用户的动作来维护一个状态,可能会导致大量的模版代码。
  • 对于所有的状态,必须创建大量的对象;这样对app的管理会成本比较高。
  • 处理一个警告的状态可能会比较困难,因为我们可能会更改配置。举个例子,如果没有网络,我们要在snackBar上显示,对于配置的更改,snackBar将会重新显示。就可用性而言,这里必须处理。

10. 项目代码

对于项目的代码,可以点击这里.

对于代码,这里列举了一下:
在这里插入图片描述

与我们有关的差不多就是MainIntent,MainState了。这里主要讲一下这个项目的逻辑:

页面初始状态页面加载状态页面正常状态页面数据错误状态
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

这里的四种状态,如果按照MVI的逻辑,使用代码可以描述为:

sealed class MyMainState {

    // 空闲状态
    object Idle : MyMainState()
    // 加载状态
    object Loading : MyMainState()
    // 加载存在数据
    data class MyMainUser(val dataList : List<User>) : MyMainState()
    // 存在异常逻辑
    data class MyError(val errorInfo : String) : MyMainState()
    
}

那么对应的State,对应的View的处理为:

when(it)  {
   is MyMainState.Idle -> {  //空闲
   }

   is MyMainState.Loading -> {   //加载
        recyclerView.visibility = View.GONE
        buttonFetchUser.visibility = View.GONE
        progressBar.visibility = View.VISIBLE
    }

    is MyMainState.MyMainUser -> {  // 存在数据
        recyclerView.visibility = View.VISIBLE
        buttonFetchUser.visibility = View.GONE
        progressBar.visibility = View.GONE

        showUserListWithData(it.dataList)
    }

    is MyMainState.MyError -> {   // 错误页面
        recyclerView.visibility = View.GONE
        progressBar.visibility = View.GONE
        buttonFetchUser.visibility = View.VISIBLE
        Toast.makeText(this@MyMainActivity, it.errorInfo, Toast.LENGTH_LONG).show()
    }

那么State有了,我们需要的Intent在哪里呢?其实我们可以这么理解,切换页面显示就是用户的一个Intent,但是Intent中存在我们定义的4种不同的State

用户,也就是我们的View通过发送这样一个Intent,来告之我们需要切换页面了,至于页面需要切换成什么,那么就需要内部通过State确定了。
具体的数据流转,大家可以下载代码查看一下就行了,个人感觉应该算是MVVM的一个改进版,或者形象一点就是将State做了进一步的封装,有好处也有坏处了。

对于初学者,这个项目里面已经做了一些简化,当然,我们可以优化这个项目来提高水平。

我希望你可以学到Android中MVI的架构。

保持学习,保持探索,保持成长。

谢谢。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值