别再让团队困惑:少有人提及的 MVI 命名规范

为什么你的 MVI 页面代码读起来比本该有的难度更高------以及一个简单的解决办法

如果你从 MVVM 迁移到了 MVI,大概率遇到过这种情况:团队盯着复杂页面的代码,绞尽脑汁也理不清流程。架构本身"没问题",但总感觉哪里不对劲。

问题根源何在?糟糕的命名规范------具体来说,是把 UI 回调和 MVI 意图(Intent)混为一谈。

让我具体说明。

MVVM 遗留习惯

在 MVVM 中,我们不会过多思考 UI 触发操作该如何转化为行为,只是直接调用 ViewModel 的方法:

c 复制代码
// MVVM - 简单直接
Button(onClick = { viewModel.login() })

TextField(onValueChange = { viewModel.updateEmail(it) })

这种方式有效且直观,但当切换到 MVI 时,这个习惯就会引发问题。

MVI 的不同之处

MVI 构建的核心是 语义清晰性 。每一个意图(Intent)都代表某件已经发生的事,是一个在单向数据流管道中传递的事件。架构本身就承载着明确的语义。

如果你模糊了"监听某件事"和"某件事已发生"的界限,就会破坏这种清晰性。

两种场景,两种规范

这个思维模型能拯救你的代码库:

1. UI 回调 → 现在时 + "On" 前缀

这些是触发器,你正在为未来可能发生的事件注册监听器。

c 复制代码
// ✅ 正确示例 - 监听触发事件
Button(onClick = { onLoginClick() })
TextField(onValueChange = { onEmailChange(it) })

可以这样理解:"当这件事发生时,执行对应的操作。"

这里用 Clicked 是错误的,因为事件尚未发生,你只是在设置监听器。

2. MVI 意图(Intent)→ 过去分词

这些是已经发生的事件,现在要发送到你的状态处理器(reducer/ViewModel) 中。

c 复制代码
// ✅ 正确示例 - 事件已发生
sealed interface LoginIntent {
    data object LoginButtonClicked : LoginIntent
    data class EmailChanged(val value: String) : LoginIntent
    data class PasswordChanged(val value: String) : LoginIntent
    data object ForgotPasswordTapped : LoginIntent
}

可以这样理解:"这件事已经发生了,需要处理。"

这里用 OnLoginClick 是多余的,因为意图(Intent)本身就定义为"已发生的事件"。

完整示例

规范的 MVI 代码应该是这样的:

c 复制代码
@Composable
fun LoginScreen(
    state: LoginState,
    onIntent: (LoginIntent) -> Unit
) {
    TextField(
        value = state.email,
        onValueChange = { onIntent(EmailChanged(it)) }  // 回调 → 意图
    )
    
    Button(
        onClick = { onIntent(LoginButtonClicked) }  // 回调 → 意图
    ) {
        Text("Login")
    }
}

注意其中的转化逻辑:

  • **onValueChange**(现在时,触发器)→ **EmailChanged**(过去时,事件)
  • **onClick**(现在时,触发器)→ **LoginButtonClicked**(过去时,事件)

MVVM 到 MVI 的思维转变

维度 MVVM MVI
UI 触发方式 直接调用方法 发送意图(Intent)
命名核心 要执行什么操作 发生了什么事
流程方向 双向感知 单向、显式
语义权重

在 MVVM 中,viewModel.login() 是一条"指令";而在 MVI 中,LoginButtonClicked 是一个"事实"。

为什么这很重要

当你的团队阅读遵循规范命名的 MVI 代码时:

  • 意图自文档化:能清晰知道每个状态变化的触发源
  • 调试更简单:日志读起来像"故事线":"EmailChanged → PasswordChanged → LoginButtonClicked → LoginFailed"
  • 新人上手更快:无需额外文档就能理解流程

速查指南

场景 命名规范 示例
UI 回调 on + 现在时 onClickonTextChange
MVI 意图 过去分词 ClickedChangedSelected

核心结论

MVI 的优势在于其显式性。不要因为沿用 MVVM 的不良命名习惯,而削弱它的优势。

UI 回调是"承诺",意图是"事实"。

按照这个原则命名,你会发现复杂页面的代码重新变得清晰易读。

相关推荐
撩得Android一次心动5 小时前
Jetpack Compose 知识点整理1【个人用】
android·学习·kotlin·android jetpack·compose
事圆则缓1 天前
MVVM 的理解与设计
android·android jetpack
alexhilton4 天前
架构测试为何需要双视图
android·kotlin·android jetpack
我命由我123455 天前
Android Jetpack Compose 开发问题:Unresolved reference ‘Icons‘.
android·java-ee·kotlin·android studio·android jetpack·android-studio·android runtime
KevinWang_5 天前
Android Compose UI 学习笔记
android jetpack
天空之城--6 天前
过去一周Android行业动态:编码技术与综合趋势精选
android·flutter·性能优化·kotlin·android jetpack
我命由我123457 天前
Linux - Linux/POSIX 路径斜杠折叠规则
linux·运维·服务器·android studio·android jetpack·android-studio·android runtime
XiaoLeisj8 天前
Jetpack Compose 知识点
android·kotlin·android jetpack·compose
我命由我123458 天前
Android 设备的日志缓冲区被写满,logcat: Unexpected EOF!
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
alexhilton10 天前
让架构边界变成可执行的测试
android·kotlin·android jetpack