Rays 采用 MVI 架构与 Jetpack Compose 的原因
什么是 MVI 架构
MVI(Model-View-Intent)是一种 Android 应用架构模式。它的核心思路是:
- Model:应用状态(数据、UI 状态)
- View:根据 Model 渲染界面
- Intent:用户的意图(点击、滑动、输入)
和传统的 MVVM 相比,MVI 的特点是单向数据流:
Intent → 处理 → 更新 Model → View 重新渲染
每个 Intent 触发一次状态更新,View 根据最新状态重新渲染,没有副作用(副作用通过单独的 Effect 通道处理)。
Rays 为什么选 MVI
作者在 GitHub README 里明确提到了 MVI 架构。选它的原因大概有:
| 优势 | 在 Rays 里的体现 |
|---|---|
| 状态可预测 | 表情库状态、搜索结果、标签列表——所有 UI 状态都有唯一真源 |
| 容易测试 | Intent → 新状态的转换可以纯单元测试 |
| 天然适配 Compose | Compose 是声明式 UI,需要可观测的状态变化来触发重组 |
| 副作用可控 | 网络请求、AI 推理、文件读写被隔离在 Effect 里,不污染 UI 状态 |
Rays 的搜索功能就是一个典型的 MVI 场景:用户输入(Intent)→ 搜索处理(可能是正则、OCR、搜索域组合)→ 得到新的搜索结果状态 → UI 根据结果重新渲染列表。
Jetpack Compose 是什么
Jetpack Compose 是 Android 的声明式 UI 框架。和传统的 View + XML 不同:
- 全 Kotlin 写 UI —— 不用 XML 布局文件
- 声明式 —— 描述"当前状态下 UI 应该长什么样",而不是手动操作 View
- 自动重组 —— 状态变了,Compose 自动重新渲染,你不用手动调用
view.setText()等 - 天然适配 Material You —— Compose 内置 Material3 组件库
Rays 为什么用 Compose
| 优势 | 在 Rays 里的体现 |
|---|---|
| 一个语言搞定前后端 | UI 和业务逻辑都用 Kotlin,不用在 XML 和 Kotlin 之间切 |
| Material You 开箱即用 | Compose 有现成的 Material3 组件,Monet 取色直接支持 |
| 组件化 | 表情卡片、搜索框、标签 Chip 都是可复用的 Composable 函数 |
| 预览方便 | @Preview 注解在 Android Studio 里直接预览 UI |
| 性能好 | Compose 只重组变化的部分,不用整个 View 树刷新 |
Rays 的界面完全是 Compose 构建的——首页、搜索页、小工具页、设置页,没有任何 XML 布局文件。
MVI + Compose 的组合
MVI 的单向数据流和 Compose 的声明式渲染是天然搭档:
- 用户操作触发 Intent(比如点了"搜索"按钮)
- Intent 被处理(执行搜索逻辑)
- 新的 State 产生(搜索结果列表)
- Compose 检测到 State 变化,自动重组 UI(渲染新列表)
中间没有 view.setVisibility() 或 adapter.notifyDataSetChanged() 这类手动 UI 更新——Compose 自己会处理。
对普通用户意味着什么
MVI + Compose 的技术选型对普通用户来说意味着:
- 界面响应流畅 —— Compose 只重绘变化的部分
- 深色/浅色切换动画顺滑 —— Compose 的状态驱动让切换很自然
- 主题色跟着壁纸变 —— Material You 的 Monet 取色和 Compose 的主题系统无缝集成
- 代码质量高 → 崩溃少 —— 架构清晰让测试更充分
你不需要知道 MVI 是什么,但你能感受到这种技术选型带来的好体验。
对 Android 开发者的启示
如果你想学 Modern Android Development(MAD),Rays 是一个很好的参考项目:
- 架构:MVI + MVI Effect
- UI:Jetpack Compose + Material 3
- 依赖注入:Hilt
- 异步:Kotlin Coroutines + Flow
- 本地存储:Room + DataStore
整套技术栈覆盖了当前 Android 开发的主流选择。