Skip to content

状态管理、路由、架构 ​

一句话定位 ​

这一模块不把"状态管理库 + 路由库"平铺成选型清单,而是按一条状态流转主线建立判断力:

状态放哪层 → 状态怎么变(单向数据流)→ 状态怎么跨页面共享 → 状态怎么跨进程存活 → 页面怎么导航与恢复。

读完后,应该能先判断"某个状态该放 UI 层、业务层还是持久层",再决定用哪个库、走哪条恢复路径。

模块目标 ​

建立 Compose / Flutter / Vue 在状态管理、路由、页面恢复、业务状态分层上的对照心智。

模块成熟度与当前优化方向 ​

当前模块可视为:L2 为主,局部主题接近 L3。

  • 已有:状态分层、恢复态、go_router、SavedStateHandle、Vue 对照等主线知识树
  • 缺口:最容易出线上事故的“状态样板”还不够集中,容易看完概念仍不会落地

所以本模块后续不应继续扩成“状态管理百科”,而应收敛为 状态事故样板库。

先看 4 类最常见状态事故 ​

例子 1:提交按钮为什么会重复发单? ​

  • 错误写法:isSubmitting、接口结果、Toast 事件全塞进一个持久 state,对页面重建和返回恢复没有边界
  • 常见后果:
    • 旋转屏幕后按钮重新可点
    • 返回页面后二次点击重复提交
    • 成功 Toast 因重建被重复消费
  • 正确拆法:
    • UI state:按钮 loading / 输入校验提示
    • 业务 state:订单创建结果 / 提交中的请求标识
    • one-shot event:Toast、导航、支付拉起结果

例子 2:列表页为什么经常“回到顶部 + 条件丢失 + 重刷一遍”? ​

  • 错误写法:把筛选条件、分页游标、滚动位置都当临时内存态,页面重建就重置
  • 正确拆法:
    • 筛选条件:恢复态或 URL query
    • 分页游标:业务 state / ViewModel
    • 滚动位置:局部恢复态 / keep-alive / rememberSaveable

这个例子最适合用来串起 Flutter、Compose、Vue 三端的状态分层对照。

本模块要回答的问题 ​

  • UI state 和业务 state 到底怎么分?
    • 一句话答:UI state 是页面渲染所需(loading / error / 选中项),业务 state 是跨页面事实(登录态 / 购物车);边界决定状态放哪层管理。
  • one-shot event 为什么总是容易写乱?
    • 一句话答:事件是一次性脉冲,塞进持久的 state 会被重建或重放(重复消费);需要独立事件通道表达,而不是当状态存。
  • Flutter 为什么不能只会 setState?
    • 一句话答:setState 只是局部 UI 重建手段,跨页面 / 跨组件共享状态需要状态提升与依赖注入来管理。
  • Riverpod / Provider / Bloc / GetX 各自适合什么?
    • 一句话答:Provider 轻量依赖注入;Riverpod 编译期安全 + 组合能力强;Bloc 事件驱动适合中大型项目;GetX 简洁但易滥用全局状态,按团队规模与可控性选。
  • Vue 的 Pinia / vue-router 和 Flutter / Compose 的对应关系是什么?
    • 一句话答:Pinia 对应全局状态仓库(Flutter 的 Riverpod / Provider、Compose 的 State 层),vue-router 对应导航栈(Flutter 的 Navigator / go_router、Compose 的 Navigation)。

知识导航树:从状态归属到页面恢复 ​

第一层:状态归属(先判断状态放哪层) ​

  • UI state:页面渲染所需,放 Composable / Widget / 组件内(remember / StatefulWidget)
  • 业务 state:跨页面事实,放 ViewModel / Riverpod / Pinia
  • 恢复态:跨配置变更 / 进程恢复的轻量锚点,放 SavedStateHandle / go_router state
  • 持久态:跨启动存活的核心数据,放 DataStore / Room / 本地库

先读:Compose / Flutter / Vue 状态管理对照

第二层:状态流转(状态怎么变) ​

  • Compose 单向数据流:State 下放 + Event 上抛
  • Flutter:setState 局部重建,跨组件靠状态提升 + 注入
  • 选型:Provider / Riverpod / Bloc / GetX 的约束强度差异

再读:Riverpod / Provider / Bloc / GetX 对比 · Jetpack Compose 状态模型、StateFlow 与重组优化 · Koin 依赖注入与 4.0 迁移 · Jetpack Compose 嵌套滚动与滚动协同 · Jetpack Compose 文本测量、自定义截断与“展开更多”

第三层:生命周期与恢复(状态怎么存活) ​

  • ViewModel / SavedStateHandle:跨旋转保留 vs 跨进程恢复的边界
  • 状态三分层:内存态 / 恢复态 / 持久态

再读:ViewModel 架构、SavedStateHandle 与进程被杀恢复 · 状态持久化、内存恢复与分层恢复策略

第四层:路由与深链(页面怎么导航) ​

  • Flutter:Navigator 1.0 vs go_router(Navigator 2.0 声明式)
  • 深链 / App Link / 合成返回栈

最后读:Flutter 路由:go_router / Navigator 体系 · 深链 (Deep Link)、App Link 与合成返回栈治理

推荐阅读路径:按问题而不是按文件名走 ​

路径 A:页面状态一旋转就丢 ​

  1. Jetpack Compose 状态模型、StateFlow 与重组优化(remember vs rememberSaveable)
  2. Jetpack Compose 文本测量、自定义截断与“展开更多”(展开更多 / 状态提升 / 文本测量)
  3. ViewModel 架构、SavedStateHandle 与进程被杀恢复(ViewModel / SavedStateHandle)
  4. 状态持久化、内存恢复与分层恢复策略(三分层)

路径 B:Flutter 状态管理怎么选型 ​

  1. Riverpod / Provider / Bloc / GetX 对比(选型对比)
  2. Compose / Flutter / Vue 状态管理对照(跨端对照)

路径 C:深链唤起后返回体验差 ​

  1. 深链 (Deep Link)、App Link 与合成返回栈治理(App Link + 合成返回栈)
  2. Flutter 路由:go_router / Navigator 体系(go_router 统一治理)

路径 D:要直接看生产级落地方案 ​

  1. 2026 生产级参考架构指南:Android (Compose/XML) 与 Flutter 最优解(Android Compose + Flutter 最优解)
  2. Koin 依赖注入与 4.0 迁移(依赖注入与架构装配:Koin 4.0 / Kotlin 2.0+ 迁移)

路径 E:滚动联动、折叠头部、BottomSheet 为什么总写乱 ​

  1. Jetpack Compose 嵌套滚动与滚动协同(滚动位移消费链)
  2. Jetpack Compose 状态模型、StateFlow 与重组优化(高频状态读取优化)
  3. Flutter 路由:go_router / Navigator 体系(Flutter 路由/页面栈对照)

导航总表 ​

导航层先回答什么对应文档
状态归属状态该放 UI / 业务 / 恢复 / 持久哪一层Compose / Flutter / Vue 状态管理对照
状态流转状态怎么变、选哪个库、约束多强Riverpod / Provider / Bloc / GetX 对比 · Jetpack Compose 状态模型、StateFlow 与重组优化
架构装配与依赖注入业务层与 ViewModel 如何解耦注入、Kotlin 2.0+ 迁移Koin 依赖注入与 4.0 迁移
文本与局部交互状态文本怎么精确截断、展开状态放哪层Jetpack Compose 文本测量、自定义截断与“展开更多”
生命周期与恢复跨旋转保留 vs 跨进程恢复的边界ViewModel 架构、SavedStateHandle 与进程被杀恢复 · 状态持久化、内存恢复与分层恢复策略
路由与深链页面怎么导航、深链怎么治理返回栈Flutter 路由:go_router / Navigator 体系 · 深链 (Deep Link)、App Link 与合成返回栈治理
滚动协同父子滚动位移如何协商消费Jetpack Compose 嵌套滚动与滚动协同

推荐复习顺序 ​

  1. 先读状态管理对照建立"状态分层"心智
  2. 再进 ViewModel / SavedStateHandle 与 Compose 状态模型(Android 主线)
  3. 再进 Riverpod 选型 与 Koin 依赖注入
  4. 再进 go_router 路由(Flutter 路由与深度链接)
  5. 再用 文本测量与展开更多 和 Compose 嵌套滚动 补两个高频真实 UI 题
  6. 最后用 Vue 对照 与 深链治理 收口跨端

对应 labs 入口 ​

类型已落地入口覆盖的事故样板
Android 恢复态基础viewmodel-savedstate-demoViewModel 抗旋转 + SavedStateHandle 抗进程死亡的基础边界
Android 恢复态样板state-persistence-demo筛选条件 / 分页游标 / 草稿正文三分层恢复
Android one-shot event 样板one-shot-event-demoToast / 导航 / 提交结果只消费一次,避免重建后重放
Android 深链返回栈样板deeplink-navigation-demoDeep Link 命中详情页后的合成返回栈治理
Android / Flutter 页面返回结果样板page-result-demo (Android) · page-result-demo (Flutter)Activity Result / Navigator.pop(result) 一次性回传,对照 SavedStateHandle 边界
Android 高级 UI 状态样板android-nested-scroll-coordination-demo · android-expandable-text-demoCompose / View 的滚动协同、文本测量、状态提升与复用边界
Flutter 路由基础flutter-routing-basic · flutter-routing-go-routerNavigator 基础与 go_router 路由声明式治理
Flutter 高级 UI 状态样板flutter-nested-scroll-coordination · flutter-expandable-text-demoSliver / NestedScrollView 协同、TextPainter 测量与列表展开状态管理

viewmodel-savedstate-demo 负责“ViewModel 抗旋转 + SavedStateHandle 抗进程死亡”的基础边界;state-persistence-demo 负责“列表页恢复态”这类真实事故样板,重点放在筛选条件、分页游标、滚动位置的分层恢复,避免两者叙事重叠。

当前最值得优先补的状态样板 ​

复习检查题 ​

  1. 为什么状态要分"UI / 业务 / 恢复 / 持久"四层管理?

    答:因为四类状态的存活边界不同:UI 态随组件重建、业务态随页面作用域、恢复态抗进程死亡、持久态跨启动存活。混层存放会导致"旋转丢状态""进程被杀丢数据"这类线上事故。

  2. remember 和 rememberSaveable 的关键区别是什么?

    答:remember 只在重组期间保留,配置变更/进程死亡即失;rememberSaveable 额外走 Bundle 序列化,能跨配置变更与进程重建恢复轻量状态。

  3. 为什么 ViewModel 能跨旋转存活、却不能跨进程存活?

    答:ViewModel 存储在进程内(ViewModelStore),旋转只是重建 Activity 但进程还在;进程被杀后 ViewModelStore 一并销毁,只有 SavedStateHandle(经 Bundle 暂存)与持久层能恢复。

  4. go_router 相比 Navigator 1.0 的核心优势是什么?

    答:基于 Navigator 2.0 的声明式路由,URL 即状态,天然支持深链统一解析、路径参数、重定向与状态恢复,适合中大型 Flutter 应用治理导航。

备注 ​

这个模块应尽量通过最小 demo 形成对照,不要只停留在概念表述。后续新增内容,优先围绕“高频状态事故”补样板,而不是再平铺很多库的概念页。

站点构建时间:2026/8/24 23:43:17