MVI 架构详解

详解MVI 架构


谷歌悄无声息的替换了官网的架构指南,配合着jetpack组件使用的MVVM一直是谷歌推崇的架构,但是如今谷歌好像也认可了MVI,把官方指南架构替换成了MVI。去Google了一下MVI,貌似国外的文章比咱们的多的多,我相信国内MVI的使用者也会越来越多(卷起来~)

什么是MVI?

在这里插入图片描述

M:model,此处的model并不是传统的数据模块,它是指用来存储视图状态UI State的一个模块 。比如请求数据时的loading、请求失败的提示页面等UI层面的变化状态。
V:view,视图模块
I:intent,此处的intent并非是我们页面跳转的intent,而是取起实际意思:意图、目的。用来响应用户在操作屏幕时的动作,用户的意图和目的。比如点击保存按钮或者下拉刷新数据等。

如何用代码实现?

MVI的实现方式目前有两种是需要我们知道的,第一种是对过去MVVM的改造升级,也就是对LiveData的升级。第二种则是使用Kotlin中的Flow去实现。两个版本的区别只是在于数据更新的方式不一样而已,一个使用LiveData,一个则是Flow。
以下是需要提前了解相关组件:

LiveData(属性监听相关的知识)
StatwFlow、MutableStateFlow、Channel

1、如果你的项目目前使用的LiveData,你可以借助LiveData属性监听的功能去实现MVI架构。LiveData的升级这里不做相关的介绍了,后期有空再补充。
参考链接:
Google 推荐使用 MVI 架构?卷起来了~
MVI 架构更佳实践:支持 LiveData 属性监听

2、响应式编程似乎是当下最潮流的编程方式,Google在其极力推荐的开发语言Kotlin中也加入了响应式编程框架Flow,目前看来Flow将逐渐取代Rxjava,毕竟Flow才是Google的亲生的。Rxjava的学习成本相对Flow还是比较高的(mmp,重新学一个框架,没有成本吗。。。)

下面争对每个模块进行代码说明:

Model层
Model是用来存储当前页面需要对用户表达的状态模型。比如Loading ,加载状态。Error数据请求失败时的状态,以及请求数据后,进行页面展示数据的状态Articles。所以他并不是我们平时所理解的存储数据模型的层级。这里model存储的时UI State。(其实我们过去的理解的model是存储的数据的,MVI中的model也差不多,只是换了一种概念,把展示数据这个动作当作存储的对象了,只要涉及到屏幕上发生状态改变的状态,都可以存储在model中)

sealed class ArticleState {
    object Idle : ArticleState()
    object Loading : ArticleState()
    data class Articles(val pagingData: PagingData<ArticleBean.DataX>) : ArticleState()
    data class Error(val error: String?) : ArticleState()
}

View层
view层就是视图模块。当然我们还需要在View层做一些基本的工作,获取Intent对象,执行用户意图。对Model中的UI State进行监听,然后刷新屏幕状态。

//通过Intent对象,用户发起获取文章列表的意图
 lifecycleScope.launch {
            viewModel.articleIntent.send(ArticleIntent.GetArticle)
        }
        
//监听UI State 发生的改变,从而刷新屏幕
lifecycleScope.launch {
            //lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {} 此处同步livedata的功能,要用
            //androidx.lifecycle:lifecycle-runtime-ktx:2.4.0版本才有改功能 绑定生命周期。activity退到后台时,不去收集数据
            //flowWithLifecycle(lifecycle, Lifecycle.State.STARTED).
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.state.collect {
                    when (it) {
                        is ArticleState.Idle -> {
                            Toast.makeText(activity, "Idle", Toast.LENGTH_LONG).show()
                        }
                        is ArticleState.Loading -> {
                            Toast.makeText(activity, "Loading", Toast.LENGTH_LONG).show()
                        }
                        is ArticleState.Articles -> {
                            pagingAdapter.submitData(it.pagingData)
                        }
                        is ArticleState.Error -> {
                            Toast.makeText(activity, it.error, Toast.LENGTH_LONG).show()
                        }
                    }
                }
            }
        }        

Intent层
Intent表示用户意图。我们可以把当前页面用户可以干的事情封装在一起(其中包含主动和被动的,比如我进入到一个列表页面,不需要用户点击任何按钮,进入页面时我们开发的时候 会主动请求列表接口,这就是用户被动意图。其实某种意义上也是主动的,他自己点进这个页面的)

sealed class ArticleIntent {
    object GetArticle : ArticleIntent()
    object GotoDetail : ArticleIntent()
    //等等。。。。
}

以上就是对MVI三个模块的代码展示。源码已经提交到了码云,有兴趣的小伙伴可以去瞅瞅~

记录学习,仅供参考

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值