当前位置: 首页 > news >正文

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
http://www.jsqmd.com/news/943423/

相关文章:

  • 如何快速批量下载音乐同步歌词:面向音乐爱好者的完整指南
  • KS-Downloader深度解析:快手无水印视频下载完整方案
  • 【早鸟优惠、连续五届稳定EI检索】第六届光学成像与图像处理国际学术会议 (ICOIP 2026)
  • 3步掌握Windows免费系统级音频均衡器:Equalizer APO完整方案
  • Gopher360:如何用游戏手柄5分钟搞定客厅电脑控制的终极指南
  • Jina Reader终极指南:3步让AI读懂整个互联网的免费方案
  • 【数据库数据恢复】Oracle数据库各类故障恢复方法与注意事项
  • Arduino渐进式夏令时时钟:非阻塞算法与时间平滑过渡实践
  • Windows 11终极瘦身方案:免费开源工具让你的电脑重获新生
  • 3步掌握缠论可视化:通达信插件终极指南
  • Claude 母公司冲刺 IPO:大模型竞争正在从“模型能力”走向“工程化落地”
  • 工业视觉异常检测:PatchCore与EfficientAD原理、实战与调优
  • Windows安卓应用安装终极指南:告别模拟器,5分钟玩转APK安装器
  • 虚拟显示的革命:ParsecVDD如何让你的Windows电脑拥有无限屏幕空间
  • XTOOL朗仁新能源维修设备打造一站式解决方案
  • 输入框自动记住常用词,点开就能搜历史、模糊匹配快速选
  • 基于Arduino与LSM303的简易伺服罗盘:从传感器到执行器的嵌入式实践
  • VS2022 + OpenCV 4.52 形状模板匹配C++工程(含MFC界面与PCI运动控制支持)
  • Axure RP 11 中文语言包终极配置指南:3步打造原生中文体验
  • NBTExplorer:开启我的世界数据编辑的新纪元,成为游戏世界的真正创造者
  • Circuit Playground 制作电子彩虹云朵帽:STEAM 亲子编程与手工指南
  • 计算机毕业设计之“暖医伴老行”老年智能医护小程序的设计与开发
  • 3步实现群晖NAS网络性能翻倍:RTL8152系列USB网卡驱动完整配置指南
  • 基于鲁本斯管原理的声控火焰与LED灯光交互系统DIY
  • Obsidian Border主题深度定制:技术架构解析与高效工作流优化
  • OpCore-Simplify终极指南:30分钟完成OpenCore EFI配置,成功率92.3%
  • Windows端口老被占?可能是这些后台进程在捣鬼(附排查与预防指南)
  • Diff Checker:3分钟掌握高效文本差异对比的终极解决方案
  • Betaflight Configurator:3步掌握无人机飞行控制配置的完整指南
  • Douyin-Downloader:抖音内容批量下载的技术解决方案