Skip to content

Flutter 生命周期总览

Flutter 生命周期不是单一“页面生命周期”,而是 App 生命周期 + Widget/Element 生命周期 + 路由栈变化 共同作用的结果。

代码索引

主题Lab 说明源码
Widget 生命周期与 AppLifecycleStateflutter-lifecycle-observerlifecycle_observer_page.dart

为什么需要

Flutter 页面“看起来像一个页面”,但底层并不是 Android Activity 那种单层对象模型。实际开发里经常踩坑:

  • 以为 build 只会执行一次,结果在返回页面、依赖变化、父组件重建时重复触发
  • 以为页面关闭就一定马上 dispose
  • 以为 Flutter 页面生命周期可以直接等同 Android Activity 生命周期
  • 以为 App 退后台只要监听 Widget 生命周期就够了,忽略了 AppLifecycleState

底层机制

1. Widget / Element / RenderObject 是三层概念

  • Widget:描述“我想长什么样”,是不可变配置
  • Element:Widget 在树中的挂载实例,负责把新旧 Widget 对应起来
  • RenderObject:真正参与布局与绘制

所以 Flutter 生命周期不能只盯着 Widget 类本身,而要理解:

  • Widget 会被频繁重建
  • Element 可能复用
  • State 可能保留,也可能销毁

2. StatefulWidget 的常见生命周期顺序

最常见顺序:

text
initState
→ didChangeDependencies
→ build
→ (多次 build)
→ deactivate
→ dispose

但要注意:

  • build 可以执行很多次
  • deactivate 不代表一定马上销毁
  • 只有最终离开树且不再复用时,才会 dispose

3. App 前后台是另一条生命周期线

Flutter 提供:

dart
WidgetsBindingObserver.didChangeAppLifecycleState

常见状态:

  • resumed
  • inactive
  • paused
  • detached
  • hidden(部分平台/版本)

这一层更接近宿主 App 的前后台切换,而不是单个页面的 push/pop。

Android / Flutter / Web / Backend 对照

维度FlutterAndroidWebBackend
页面创建initStateonCreate路由挂载 / 首次 render请求进入 handler
页面可见可交互build 完成后进入前台交互onResumeDOM 可交互请求处理中
页面离开但可能回退路由栈保留,页面可能仅失焦onPause / onStop页面被遮挡或切换路由缓存无直接对应
最终销毁disposeonDestroy组件 unmount请求结束 / 对象释放
App 前后台AppLifecycleStateonStart/onStop + 进程状态tab visibility进程级守护/无前后台

常见场景

1. 列表页进入详情页再返回

  • 列表页通常不会立刻销毁
  • 返回后往往只是再次 build
  • 如果你把“昂贵初始化”写在 build 里,就会重复执行

对应 Labflutter-lifecycle-observer · lifecycle_observer_page.dart

2. App 退后台暂停轮询/动画/定位

这类逻辑不能只靠页面 dispose,因为:

  • 页面可能还在栈里
  • 但 App 已经退后台

这时要监听 AppLifecycleState.paused/resumed

3. Provider / Stream / Controller 释放时机判断

若资源跟页面实例强绑定,通常在 dispose 里释放;若资源跟更上层作用域绑定,则不能简单放当前页面 dispose

常见坑

现象修法
build 中做网络请求返回页面或父组件刷新时重复请求首次加载放 initState 或受控状态层
把 App 前后台逻辑写进页面 push/pop退后台不生效监听 WidgetsBindingObserver
误把 deactivate 当最终销毁日志顺序判断错误真正释放放 dispose
页面销毁后仍回调 setStatesetState() called after dispose()回调前检查 mounted

与相近概念对比

概念关注点适合处理的问题
initStateState 首次创建一次性初始化、controller 创建
didChangeDependencies依赖变动依赖 InheritedWidget 的初始化
build渲染描述纯 UI 组装
deactivate暂时离开树很少作为主要业务钩子
dispose最终释放controller / listener / stream 关闭
didChangeAppLifecycleStateApp 前后台切换暂停轮询、恢复订阅、页面级埋点

对应实验

各章节内已嵌入跳转链接;此处汇总全部 Lab:

Lab说明源码
flutter-lifecycle-observerflutter-lifecycle-observerlifecycle_observer_page.dart

复习检查题

  1. 为什么 Flutter 里不能把页面生命周期简单理解成 Android Activity 生命周期?

    :因为 Flutter 还有 Widget / Element / RenderObject 三层;页面 push/pop、父组件重建、依赖变化都会触发 Widget 重建,而不一定对应宿主页面的创建销毁。

  2. 为什么 build 不适合放一次性初始化逻辑?

    :因为 build 会多次执行,返回页面、父组件重建、依赖变化都可能触发;一次性初始化更适合放 initState 或受控状态层。

  3. App 退后台暂停任务应该主要监听什么?

    :主要监听 WidgetsBindingObserver.didChangeAppLifecycleState,而不是只依赖页面 dispose

速记

  • initState:建一次
  • build:可能很多次
  • deactivate:离开树,不一定销毁
  • dispose:最终释放
  • App 前后台:看 AppLifecycleState