别再让团队困惑:少有人提及的 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 回调是"承诺",意图是"事实"。

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

相关推荐
zh_xuan5 小时前
Android Jetpack 使用Room数据库
android·android jetpack·room
alexhilton3 天前
Jetpack Compose中的富文本输入
android·kotlin·android jetpack
海盐芝士不加糖3 天前
我又又又辞职了,然后做了一款“离线版微信”
kotlin·app·android jetpack
XiaoLeisj4 天前
Android 媒体能力实战:从 Media3 音视频播放到 CameraX 拍照与视频录制
android·音视频·媒体·android jetpack
段娇娇5 天前
Android jetpack ViewBinding(一)使用篇
android·android jetpack
hnlgzb6 天前
常见的Android Jetpack库会有哪些?这些库中又有哪些常用类的?
android·android jetpack
木子予彤6 天前
直破 Android 17 大屏困局:Navigation 3 架构深度解析
android·android jetpack
阿巴斯甜7 天前
DisposableEffect的使用:
android jetpack
阿巴斯甜7 天前
rememberCoroutineScope 的使用
android jetpack