一、StatefulWidget 生命周期
这是 Flutter 中最常用、最重要的生命周期,每个StatefulWidget都有完整的生命周期流程。
1. 生命周期流程图
2. 生命周期方法
class MyWidget extends StatefulWidget { @override _MyWidgetState createState() => _MyWidgetState(); } class _MyWidgetState extends State<MyWidget> { // 1. 构造函数(不是生命周期方法,但最先执行) _MyWidgetState() { print('1. 构造函数执行'); } // 2. initState - 状态初始化 @override void initState() { super.initState(); print('2. initState - 只执行一次'); // 初始化数据、监听器、Stream、动画控制器等 // 注意:不能在这里调用 BuildContext 的依赖方法 } // 3. didChangeDependencies - 依赖变化时调用 @override void didChangeDependencies() { super.didChangeDependencies(); print('3. didChangeDependencies - 依赖的 InheritedWidget 变化时调用'); // 在 initState 之后立即调用,之后每次依赖变化都会调用 } // 4. build - 构建 UI @override Widget build(BuildContext context) { print('4. build - UI 构建'); return Container( child: Text('Hello'), ); } // 5. didUpdateWidget - Widget 配置更新时调用 @override void didUpdateWidget(covariant MyWidget oldWidget) { super.didUpdateWidget(oldWidget); print('5. didUpdateWidget - Widget 重建且配置变化时调用'); // 当父 Widget 重建并传递了新参数时调用 } // 6. setState - 触发重建(不是生命周期方法,但常用) void updateData() { setState(() { print('6. setState - 触发 UI 重建'); // 更新状态 }); } // 7. deactivate - 从树中移除时调用 @override void deactivate() { super.deactivate(); print('7. deactivate - State 从树中移除'); // 当 Widget 被移除(如路由返回)时调用 } // 8. dispose - 永久销毁 @override void dispose() { print('8. dispose - 永久销毁,释放资源'); // 取消监听器、销毁动画控制器、关闭 Stream 等 super.dispose(); } // 9. reassemble - 热重载时调用(仅开发环境) @override void reassemble() { super.reassemble(); print('9. reassemble - 热重载时调用'); } }二、App 生命周期(WidgetsBindingObserver)
通过WidgetsBindingObserver可以监听应用的前后台切换、系统弹窗等。
1. 监听应用状态
class AppLifecycleDemo extends StatefulWidget { @override _AppLifecycleDemoState createState() => _AppLifecycleDemoState(); } class _AppLifecycleDemoState extends State<AppLifecycleDemo> with WidgetsBindingObserver { AppLifecycleState? _appLifecycleState; @override void initState() { super.initState(); // 添加观察者 WidgetsBinding.instance.addObserver(this); } @override void dispose() { // 移除观察者 WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { setState(() { _appLifecycleState = state; }); switch (state) { case AppLifecycleState.resumed: print('应用回到前台'); break; case AppLifecycleState.inactive: print('应用处于非活动状态(如接电话)'); break; case AppLifecycleState.paused: print('应用进入后台'); break; case AppLifecycleState.detached: print('应用即将被销毁'); break; case AppLifecycleState.hidden: print('应用隐藏(iOS 特有)'); break; } } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Text('App 状态: $_appLifecycleState'), ), ); } }三、路由生命周期
1. RouteObserver 监听路由变化
// 创建 RouteObserver final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>(); // 在 MaterialApp 中注册 class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( navigatorObservers: [routeObserver], // 注册观察者 home: HomePage(), ); } } // 使用 RouteAware 监听页面生命周期 class MyPage extends StatefulWidget { @override _MyPageState createState() => _MyPageState(); } class _MyPageState extends State<MyPage> with RouteAware { @override void didChangeDependencies() { super.didChangeDependencies(); // 订阅路由观察者 routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute); } @override void dispose() { // 取消订阅 routeObserver.unsubscribe(this); super.dispose(); } // 页面被推入时调用 @override void didPush() { print('页面被推入'); } // 页面被弹出时调用 @override void didPop() { print('页面被弹出'); } // 页面被新的页面覆盖时调用 @override void didPushNext() { print('有新页面推入,当前页面被覆盖'); } // 覆盖当前页面的页面被弹出时调用 @override void didPopNext() { print('上面的页面被弹出,当前页面重新显示'); } @override Widget build(BuildContext context) { return Scaffold( body: Center(child: Text('路由生命周期示例')), ); } }2. 使用 Navigator 观察者
class MyNavigatorObserver extends NavigatorObserver { @override void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) { print('推入路由: ${route.settings.name}'); } @override void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) { print('弹出路由: ${route.settings.name}'); } @override void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) { print('移除路由: ${route.settings.name}'); } @override void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) { print('替换路由: ${oldRoute?.settings.name} -> ${newRoute?.settings.name}'); } } // 使用 MaterialApp( navigatorObservers: [MyNavigatorObserver()], // ... )四、KeepAlive 生命周期(AutomaticKeepAliveClientMixin)
用于保持页面状态,如 Tab 页切换时保持页面不被销毁。
class KeepAlivePage extends StatefulWidget { @override _KeepAlivePageState createState() => _KeepAlivePageState(); } class _KeepAlivePageState extends State<KeepAlivePage> with AutomaticKeepAliveClientMixin { int _counter = 0; @override bool get wantKeepAlive => true; // 保持页面状态 @override Widget build(BuildContext context) { // 必须调用 super.build super.build(context); return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('计数: $_counter'), ElevatedButton( onPressed: () { setState(() { _counter++; }); }, child: Text('增加'), ), ], ), ), ); } }五、生命周期汇总
| 生命周期 | 调用时机 | 主要用途 |
|---|---|---|
| createState | State 对象创建时 | 创建 State 实例 |
| initState | Widget 插入树后 | 初始化数据、监听器、动画 |
| didChangeDependencies | 依赖变化时 | 处理 InheritedWidget 变化 |
| build | 每次重建时 | 构建 UI |
| didUpdateWidget | Widget 配置变化时 | 响应父 Widget 参数变化 |
| setState | 手动调用时 | 触发 UI 重建 |
| deactivate | State 从树移除时 | 临时移除前的清理 |
| dispose | State 永久销毁时 | 释放资源、取消订阅 |
| didChangeAppLifecycleState | 应用前后台切换 | 暂停/恢复资源 |
| didPush/didPop | 路由变化时 | 页面埋点、状态管理 |
备注:
在
dispose中释放所有资源(定时器、Stream、动画控制器)。使用
mounted检查 State 是否还在树中,避免在dispose后调用setState。利用
WidgetsBindingObserver监听应用状态,优化资源使用。使用
RouteObserver追踪页面访问,便于埋点和分析。