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
相关产品推荐
相关产品推荐

