MVI架构

最近准备去学一下新出的MVI架构,看了半天后才发现目前主流的MVI都是用kotlin语言写...去查阅kotlin的基础语法,然后发现还用到了携程等用法...去查阅携程用法,终于...现在再回头来看才终于看懂了些。

1、什么是MVI

MVI是继MVC、MVP、MVVM之后又出的一种架构,(Model-View-Intent)

  • Model: 主要指UI状态(State)。例如页面加载状态、控件位置等都是一种UI状态
  • View: 可能是一个Activity或者任意UI承载单元。MVI中的View通过订阅Model的变化实现界面刷新
  • Intent: 此Intent不是Activity的Intent,用户的任何操作都被包装成Intent后发送给Model层进行数据请求

1、基于kotlin的架构

MVI架构中,将整个页面的状态存放于单一的类中,而且这个类必须是Kotlin的data class,kotlin的这个特殊的类自带了copy功能,非常方便去更新部分的属性。
目前android主流的MVI是基于协程+flow+viewModel去实现的,

就是把所有更新ui的方法转为intent,在viewModel中使用flow监听,
然后把界面数据状态转为state,在view中使用flow监听
view中使用时发送intent,viewModel监听到操作,修改对应的state,然后view监听到操作,更新ui(界面变化是数据流的末端,界面消费上游产生的数据,并随上游数据的变化进行刷新。数据永远在一个环形结构中单向流动,不能反向流动,而且能改变ui的数据只有state)

在这里插入图片描述

2、为什么要用MVI

优点

  • UI的所有变化来自State,所以只需聚焦State,架构更简单、易于调试
  • 数据单向流动,很容易对状态变化进行跟踪和回溯
  • state实例都是不可变的,确保线程安全
  • UI只是反应State的变化,没有额外逻辑,可以被轻松替换或复用

缺点

  • 所有的操作最终都会转换成State,所以当复杂页面的State容易膨胀
  • state是不变的,每当state需要更新时都要创建新对象替代老对象,这会带来一定内存开销
  • 有些事件类的UI变化不适合用state描述,例如弹出一个toast或者snackbar

3、MVI在代码中怎们使用

 想要在代码中使用MVI需要知道kotlin携程flow和携程作用域的用法

1、kotlin携程

协程是一种「并发设计模式」。作用是简化异步执行的代码。它可以帮助管理一些耗时的任务,以防耗时任务阻塞主线程。协程可以用同步的方式写出异步代码,代替了传统的回调方式,让代码更具有可读性。

优点

  • 轻量:可在单个线程上运行多个协程,因为协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作;
  • 内存泄露更少:使用结构化并发机制在一个作用域内执行多个操作;
  • 内置取消支持:取消功能会自动通过正在运行的协程层次结构传播;
  • Jetpack集成:许多 Jetpack 库都包含提供全面协程支持的扩展。某些库还提供自己的协程作用域,可供您用于结构化并发。
    //使用协程
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"

 2、Flow

Flow 是 Kotlin 官方基于协程构建的用于响应式编程的API。响应式编程简单来说就是使用异步数据流进行编程 。协程中,使用挂起函数仅可以异步返回单个值,而 Flow 则可以异步返回多个值,并补全kotlin语言中响应式编程的空白。

监听方法

 
userIntent.consumeAsFlow().collect {//监听 userIntent 中的方法
                when (it) {//监测到 FetchUser被触发
                    is MainIntent.FetchUser -> fetchUser()
                }
            }

 触发方法

 lifecycleScope.launch {//携程作用域
                viewModel.userIntent.send(MainIntent.FetchUser)
            }

3、携程作用域

lifecycleScope 和viewModelScope
* lifecycleScope.launch{} 只能在Activity、Fragment中使用,会绑定Activity和Fragment的生命周期
* 协程内的阻塞不会影响协程外
* 协程体是异步执行的,但是可以在其中做UI操作。线程也是异步的,但是不能更新UI,线程需要先切换到主线程。
* 默认情况下协程中的内容是串行的
* 如果需要并行,例如请求多个接口拿到数据后才能进行操作,可以使用 async{}
* 手动停止的方法 job?.cancel()
* 会绑定调用者的生命周期,因此通常情况下不需要手动去停止
viewModelScope.launch{} 只能在ViewModel中使用,绑定ViewModel的生命周期

 为什么要用:

当启动多个协程时,无论是追踪协程状态,还是单独取消各个协程,都是件让人头疼的事情。 * 不过,我们可以通过直接取消协程启动所涉及的整个作用域 (scope) 来解决这个问题,因为这样可以取消所有已创建的子协程。

    //viewModelScope
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
    //lifecycleScope
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'

在代码中的用法

 lifecycleScope.launch { //携程作用域
           ...
        }
viewModelScope.launch {//携程作用域 能自动管理生命周期,自动取消请求
           ...
        }

其他方法这里就不演示了,想要了解的自行百度下吧,东西挺多的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值