Compose 状态 / 协程 总图(工程版)
┌─────────────────────────────┐
│ User Interaction │
│ click / scroll / input │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ Composable(UI) │
│─────────────────────────────│
│ 1️⃣ onClick / onEvent │
│ └─ 调用 ViewModel 方法 │
│ │
│ 2️⃣ collectAsStateWithLifecycle
│ └─ 订阅 State Flow │
│ │
│ 3️⃣ remember │
│ └─ 本地 UI 状态 │
│ │
│ 4️⃣ LaunchedEffect │
│ └─ 收一次性事件 │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ ViewModel │
│─────────────────────────────│
│ 5️⃣ 业务逻辑 / 决策 │
│ │
│ 6️⃣ StateFlow<UiState> │
│ └─ 持续状态(UI) │
│ │
│ 7️⃣ SharedFlow<Event> │
│ └─ 一次性事件(导航等) │
│ │
│ 8️⃣ viewModelScope.launch │
│ └─ 后台协程 │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ Coroutine / Data Layer │
│─────────────────────────────│
│ 9️⃣ suspend / Flow │
│ └─ IO / 网络 / 数据库 │
│ │
│ 🔁 emit 新数据 │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ State 更新 → 重组 │
│─────────────────────────────│
│ State 改变 │
│ → Composable 重组 │
│ → UI 更新 │
└─────────────────────────────┘
用一句话读懂这张图
事件往下走,状态往上走
- 👇 事件:UI → ViewModel → 协程
- 👆 状态:数据 → StateFlow → UI
三条"生命线"(你一定要记)
① 状态线(State Line)
Data → StateFlow → collectAsStateWithLifecycle → UI
- 可以重放
- 可以恢复
- 驱动 UI
② 事件线(Event Line)
ViewModel → SharedFlow → LaunchedEffect → UI
- 只消费一次
- 不能放 State
- 导航 / Toast / Snackbar
③ 生命周期线(Lifecycle Line)
Composable
├─ remember → 重组安全
├─ LaunchedEffect → 自动 cancel
└─ collectAsStateWithLifecycle → STARTED 才收集
每个关键组件"该干嘛"
remember
解决重组问题
- 本地 UI 状态
- 不进 ViewModel
StateFlow
UI 的"唯一真相源"
- 可恢复
- 可重放
SharedFlow / Channel
一次性动作
- 导航
- 弹 Toast
LaunchedEffect
副作用容器
- 协程入口
- 绑定 Composable 生命周期
collectAsStateWithLifecycle
Flow → State 的桥
- 自动感知生命周期
- 官方推荐
常见错误 vs 正确流向(对照)
❌ 错误
ViewModel 直接 navigate
Composable 存业务状态
State 控制导航
✅ 正确
Composable 发事件
ViewModel 决策
UI 执行导航
一眼判断该不该用 remember / Effect
| 你想做的事 | 用什么 |
|---|---|
| 跨重组记住值 | remember |
| 启动协程 | LaunchedEffect |
| UI 状态 | StateFlow |
| 一次性事件 | SharedFlow |
| 收 Flow 更新 UI | collectAsStateWithLifecycle |
最后一段(工程级总结)
Compose 是"状态驱动 UI 的协程系统"
你不是在写 View,
你是在搭一条:
事件 ↓ 状态 ↑的单向数据流。