You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MVI+MVVM架构下:输入数据应由哪个组件负责存储?

MVI+MVVM架构下输入name数据的存储方案

刚好在MVI+MVVM的混合架构里处理过类似的列表项输入场景,我来给你梳理下最佳实践:

在MVI+MVVM的结合架构中,所有UI相关的状态(包括用户输入的name)都应该由ViewModel持有的UI State来统一存储,核心原因是MVI强调「单一可信数据源(Single Source of Truth)」,而MVVM里ViewModel本身就是状态管理的核心,两者结合后,状态绝对不能分散在View层(比如ListViewItem的实例里)。

具体实现思路可以分成这几步:

  • 第一步:在ViewModel的UI State中定义包含id和可选name的数据结构,比如:
// 单个列表项的状态,不可变(符合MVI的State不可变原则)
data class ListViewItem(val id: String, val name: String?)

// 页面整体的UI State
data class PageUiState(val items: List<ListViewItem>)
  • 第二步:当用户在输入框中输入name时,View层需要把这个操作转换成MVI的Intent(比如UpdateItemNameIntent(id: String, newName: String)),发送给ViewModel。
  • 第三步:ViewModel接收Intent后,基于当前的UI State,生成一个新的State(更新对应id的ListViewItem的name字段),然后将新State分发给View层。
  • 第四步:View层(不管是Jetpack Compose的LazyColumn还是传统RecyclerView)只需要绑定State中的数据,输入框的内容直接从State里的name字段读取,完全不需要自己持有输入状态。

这样做的好处非常明显:

  • 保证状态的一致性:所有输入数据都存在单一的State里,不会出现View层和ViewModel数据不一致的情况
  • 便于回溯和调试:MVI的State是不可变的,每次更新都有完整的状态快照,排查问题时可以轻松查看状态变化轨迹
  • 按钮点击处理更简单:当点击按钮需要处理带name的Item时,ViewModel直接从当前的UI State中过滤即可,不需要从View层逐个收集数据

举个小例子,ViewModel里处理Intent的逻辑大概是这样:

fun handleIntent(intent: PageIntent) {
    when(intent) {
        is PageIntent.UpdateItemNameIntent -> {
            val updatedItems = currentState.items.map {
                if (it.id == intent.id) it.copy(name = intent.newName) else it
            }
            _uiState.value = currentState.copy(items = updatedItems)
        }
        // 其他Intent处理...
    }
}

内容的提问来源于stack exchange,提问作者Lingviston

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:01:28