news 2026/6/3 16:54:51

Compose 声明式编程 状态 数据传递模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Compose 声明式编程 状态 数据传递模式

Compose 声明式编程 状态 & 数据传递模式

Compose 里"哪种 API 存哪种状态"很容易选错——选轻了状态被旋转吃掉,选重了在该用remember的地方架个 ViewModel。
这份文档把项目里已经在用的几种模式按"作用域 + 异步性"两条轴排一下,给出选型决策、样例代码和踩过的坑。


0. 一句话决策表

我要存的 / 做的用什么
按钮按下、对话框开关、tab 选中等纯视觉态remember { mutableStateOf(...) }
旋转 / 进后台要保住的 UI 状态rememberSaveable
由其他可观察状态算出来的派生值derivedStateOf
一次性异步拉取的结果(屏幕私有)produceState
监听某些 key 变化跑副作用LaunchedEffect(key)
点击事件里要启动协程rememberCoroutineScope
复杂状态机 / 跨重组 / 需要测试 / 需要分页ViewModel+StateFlow
多屏共享 / 活动级单例Activity 作用域ViewModel
沿组合树隐式传递(导航回调、当前用户身份)CompositionLocalLocalBack/LocalNavigationTo/LocalCurrentUserId
把多个 list 参数收成一个传给子 Composabledata class包装
让子 Composable 不关心数据形态,只渲染tabContent: @Composable () -> Unitslot lambda

1. 作用域 × 异步性 四象限

┌──────────────────────────┬──────────────────────────┐ │ Composition 内(短) │ ViewModel 内(长) │ ┌───────────────────┼──────────────────────────┼──────────────────────────┤ │ 同步 / 即时 │ remember / mutableStateOf│ ViewModel 普通字段 │ │ │ rememberSaveable │ │ ├───────────────────┼──────────────────────────┼──────────────────────────┤ │ 异步 / 协程 │ LaunchedEffect │ StateFlow + viewModelScope│ │ │ produceState │ .launch │ │ │ rememberCoroutineScope │ │ └───────────────────┴──────────────────────────┴──────────────────────────┘
  • 左侧生命周期是 “Composable 在屏 / 离屏” —— 旋转、Tab 切走 + 切回都会重建。
  • 右侧生命周期是 ViewModelStore —— 跟 Activity 走,旋转不丢,离开屏幕也保留(直到 ViewModelStore 清理)。

2. 各模式详解

2.1remember { mutableStateOf(...) }—— 最轻量的本地状态

varsheetOpenbyremember{mutableStateOf(false)}Button(onClick={sheetOpen=true}){Text("Open")}if(sheetOpen){BottomSheet(onDismiss={sheetOpen=false})}

适合:纯 UI 视觉状态(开关、动画 trigger、tab index 等);与数据层无关。

不适合

  • 想让旋转后还保留 → 用rememberSaveable
  • 想让多个 composable 共享 → 提升到父组件,或上 ViewModel。
  • 想存 List / 复杂对象 → 想清楚是不是该上 StateFlow。

经典陷阱:把 props 当 seed 写进 remember:

// ❌ 错的——props.followedByMe 变化后 isFollowing 不会更新varisFollowingbyremember{mutableStateOf(props.followedByMe)}// ✅ 加 key——props 变化时 remember 块重建,按新 props seedvarisFollowingbyremember(props.followedByMe){mutableStateOf(props.followedByMe)}

第二种写法在OtherScreenproduceState时承担过 follow 按钮的状态管理。


2.2rememberSaveable—— 旋转保活的本地状态

varisLandscapebyrememberSaveable{mutableStateOf(false)}

适合:旋转 / 进后台后还想保住的纯 UI 状态。

限制

  • 只能存Parcelable/Serializable/ 内置基本类型。自定义类要写Saver
  • 跨进程 kill 也能恢复(依赖 SavedInstanceState)。

反例 / 坑:用rememberSaveable存"一次性事件完成"flag(典型:“已经跳过页”)——见anti-pattern #1


2.3derivedStateOf—— 派生状态,避免抖动

valshouldLoadMorebyremember(pagerState){derivedStateOf{valtotal=state.items.size total>0&&pagerState.settledPage>=total-PRELOAD_AHEAD&&state.hasMore&&!state.isLoadingMore}}

关键性能特性:只有当内部读到的可观察状态计算出的结果发生变化,下游订阅者才会被通知。换句话说,pager 滑动每帧 offset 抖动不会让shouldLoadMore重新通知;只有 false→true / true→false 翻转才会。

适合

  • 监听多个 state 算出一个 boolean / 简化值。
  • LaunchedEffect
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/3 16:54:12

语义认知内容操作系统内核 v1.1:从生成到进化的架构跃迁

语义认知内容操作系统内核 v1.1:从生成到进化的架构跃迁一、系统定位与技术背景1.1 为什么需要语义认知内核传统内容生成系统存在三个根本性缺陷: 无评估机制:生成即输出,无法判断内容质量 无记忆能力:每次生成都是从零…

作者头像 李华
网站建设 2026/6/3 16:52:20

Anki终极指南:如何用智能记忆卡片轻松掌握任何知识

Anki终极指南:如何用智能记忆卡片轻松掌握任何知识 【免费下载链接】anki Anki is a smart spaced repetition flashcard program 项目地址: https://gitcode.com/GitHub_Trending/an/anki 你是否曾为记不住重要信息而烦恼?无论是学习外语词汇、备…

作者头像 李华
网站建设 2026/6/3 16:50:13

Obsidian Border主题深度定制:技术架构解析与高效工作流优化

Obsidian Border主题深度定制:技术架构解析与高效工作流优化 【免费下载链接】obsidian-border A theme for obsidian.md 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-border 在知识管理工具日益复杂的今天,Obsidian Border主题通过其…

作者头像 李华