TITLE:不再把滚动位置塞进ViewModel:snapshotFlow用1个快照终结争论 为什么把滚动位置传给业务层?两三年前,答案常是“交给 Flow 统一处理”。今天回看,那种做法硬生生把临时 UI 状态塞进架构层,导致本该轻量的载体变成了转发站。根源在于习惯假设一切状态都归架构管,直到 Compose 的 snapshotFlow 摆出了更自然的姿势。 Jetpack Compose 把快照系统开放后,转折来了。以前想响应滚动、选中这类界面专属变化,只能把 Compose 状态拷贝到业务层的 StateFlow,再借协程收集去触发埋点或搜索去抖。看似活用 Flow,实则是绕道:UI 自己的状态,非得借一层中间人才能执行副作用。Compose 团队发现这个别扭点,让 snapshotFlow 切了进来——“状态待在哪,观察就在哪”。 snapshotFlow 直接让 Compose 状态成为 Flow,无需中间人。以埋点为例:过去 LazyColumn 得把滚动索引发给业务载体,载体再转给埋点模块;现在只需在 UI 层写 snapshotFlow { listState.firstVisibleItemIndex },collect 后直接调用埋点。滚动位置这类为界面而生的值,从未离开界面层,业务载体也不用再为临时状态负责。 好处不止少写模板代码。一旦滚动、选中、搜索框内容这些 UI-only 状态被圈定在 UI 层,分工就明朗了:界面管渲染交互,业务逻辑处理领域数据,二者通过事件和不可变数据流衔接。测试也直观——触发与副作用都在同一范围,无需跨层捏造数据。尤其 snapshotFlow 产出的就是标准 Flow,debounce、filter、combine 等操作符直接可用。 由此浮现一条法则:若某状态仅用于渲染,它就该留在 UI 里。LazyList 可见项索引是,TextField 提交前的逐次变化也是。过去把这类值统统拉进业务容器,理由是“统一管理可观察数据”,却模糊了边界。Compose 快照系统等于在框架层恢复了这个边界,副作用可以和触发状态物理上靠得更近。 从开发节奏看,这样的调整也释放了维护成本。以往新增一个交互副作用,常要在业务层和 UI 间来回铺管线;现在多数场景只需在组合范围加 LaunchedEffect 搭配 snapshotFlow。需求变更时,收集的增减更
![]()
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.