【Orbit-mvi】Android MVI 框架推荐与示例,简洁优雅的实现MVI代码结构

项目介绍

示例程序

  • 预览
  • 添加依赖项到build.gradle
scss 复制代码
implementation("org.orbit-mvi:orbit-core:9.0.0")
implementation("org.orbit-mvi:orbit-viewmodel:9.0.0")

代码结构

  1. 为页面创建一个状态类XXState,包含所有状态信息,注意state中的字段是val的,不可变的,每次页面刷新都是发出一个新的state对象
kotlin 复制代码
data class MyState(
    val isLike: Boolean = false, // 是否点赞
    val likeCount: Int = 0, // 点赞数
)
  1. 为页面创建一个副作用类XXEffect,一些一次性事件,类如Toast, Loading都放在这里
kotlin 复制代码
sealed class MyEffect {
    data class Loading(val show: Boolean, val text: String? = null) : MyEffect()
    data class Toast(val text: String) : MyEffect()
}
  1. 为页面创建ViewModel, 实现ContainerHost接口
kotlin 复制代码
class MyViewModel : ViewModel(), ContainerHost<MyState, MyEffect> {
    override val container = container<MyState, MyEffect>(MyState(likeCount = 232))

    fun like() = intent {
        if (state.isLike) {
            postSideEffect(MyEffect.Toast("已点赞,不可重复点赞")) // 发送toast事件
            return@intent
        }
        postSideEffect(MyEffect.Loading(show = true, text = "请稍候...")) // 发送loading
        delay(500) // 模拟网络请求
        reduce {
            // 在此处生成新的state对象, 以便UI观察这个新state而改变
            state.copy(isLike = true, likeCount = state.likeCount + 1)
        }
        postSideEffect(MyEffect.Loading(show = false)) // 关闭loading
        postSideEffect(MyEffect.Toast("点赞成功"))
    }
}
  1. 实现页面逻辑, 此处为Activity
kotlin 复制代码
// 监听state变化和sideEffect事件
viewModel.observe(this, state = ::render, sideEffect = ::handleEffect)

// 点击事件,此处无需过度封装为一个Intent, 直接调viewmodel函数就行
binding.tvLike.setOnClickListener {
    viewModel.like()
}

// 渲染UI
fun render(state: MyState) {
    ...
    binding.textView.text = state.likeCount.toString() // 更新点赞数
}

// 处理副作用
fun handleEffect(effect: MyEffect) {
    when (effect) {
        is MyEffect.Toast -> {
            Toast.makeText(this, effect.text, Toast.LENGTH_SHORT).show()
        }
    }
}

总结

  • 可以看到, 框架已经帮我们封装好了Kotlin协程和Flow的实现,我们只需要在viewModel中使用intent{}即可, 并且侵入性较小,只需要viewModel实现一个接口就行
  • 对于副作用,例如Toast,使用postSideEffect()发出新的Effect对象
  • 对于页面刷新,例如变更点赞数,使用reduce{},将state.copy()出一个新的对象并发出
  • 本实例程序源码: Github
相关推荐
周杰伦_Jay21 分钟前
【 RocketMQ 全解析】分布式消息队列的架构、消息转发与快速实践、事务消息
分布式·算法·架构·rocketmq·1024程序员节
腾讯云开发者1 小时前
腾讯元宝搜索实践:大模型时代,AI 如何让搜索焕发新生
架构
Somehow0071 小时前
从Binlog到消息队列:构建可靠的本地数据同步管道(macOS本地部署Canal & RocketMQ并打通全流程)
后端·架构
百锦再1 小时前
国产数据库替代MongoDB的技术实践:金仓数据库赋能浙江省人民医院信息化建设新展望
java·开发语言·数据库·mongodb·架构·eclipse·maven
小二李3 小时前
nestjs 架构篇:控制器、服务、数据访问
架构
消失的旧时光-19434 小时前
Flutter 响应式 + Clean Architecture / MVU 模式 实战指南
android·flutter·架构
Java烘焙师4 小时前
架构师必备:限流方案选型(使用篇)
redis·架构·限流
404未精通的狗4 小时前
(数据结构)栈和队列
android·数据结构
恋猫de小郭5 小时前
今年各大厂都在跟进的智能眼镜是什么?为什么它突然就成为热点之一?它是否是机会?
android·前端·人工智能
朱嘉鼎5 小时前
寄存器编写LED程序
stm32·单片机·架构·keilmdk