生命周期
本文介绍Flutter的状态组件
的生命周期
,并详细介绍各个阶段函数的执行时机和应用场景。
# 组件生命周期
StatefulWidget 生命周期
执行顺序,从上往下
名称 说明 createState 创建 State 只执行 1 次 initState 初始 State, mounted 等于 true, 只执行 1 次 didChangeDependencies 父或祖先 widget 中的 InheritedWidget 改变时会被调用 build UI 被重新渲染的时候多次执行 addPostFrameCallback 渲染结束回调,只执行 1 次 didUpdateWidget 父类 setState 后,子类就会触发 deactivate 从组件树中移除 State 时调用 dispose 组件被释放时调用 initState
初始状态数据。// 初始 State, mounted 等于 true, 只执行 1 次 void initState() { // TODO: implement initState super.initState(); print('initState'); }
1
2
3
4
5
6
7build
渲染视图,可多次。Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('无状态')), body: Column( children: [ ElevatedButton( onPressed: () { if (mounted == true) { setState(() { imgUrl = imgUrl == img1 ? img2 : img1; }); } }, child: const Text("切换图片"), ), Text(imgUrl) ], ), ), ); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23mounted
状态。
flutter 分配完你的组件树位置,会设置 mounted 为 true,需要在 mounted == true 情况下,调用 setState() 来更新 UI ,这才是安全的操作。。
ElevatedButton( onPressed: () { if (mounted == true) { setState(() { imgUrl = imgUrl == img1 ? img2 : img1; }); } }, child: const Text("切换图片"), )
1
2
3
4
5
6
7
8
9
10didChangeDependencies
父或祖先 widget 中的 InheritedWidget 改变时会被调用。// 父或祖先 widget 中的 InheritedWidget 改变时会被调用 void didChangeDependencies() { // TODO: implement didChangeDependencies super.didChangeDependencies(); print('didChangeDependencies'); }
1
2
3
4
5
6
7didUpdateWidget
父类 setState 后,子类就会触发。void didUpdateWidget(covariant BannerWidget oldWidget) { // TODO: implement didUpdateWidget super.didUpdateWidget(oldWidget); print('didUpdateWidget'); }
1
2
3
4
5
6addPostFrameCallback
渲染结束回调,只执行 1 次。// 初始 State, mounted 等于 true, 只执行 1 次 void initState() { // TODO: implement initState super.initState(); imgUrl = img1; print('initState'); // 渲染结束回调,只执行 1 次 SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { print('SchedulerBinding'); print(timeStamp); }); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14deactivate
从组件树中移除 State 时调用。void deactivate() { super.deactivate(); print("deactivate"); }
1
2
3
4
5dispose
组件被释放时调用。void dispose() { print("dispose"); super.dispose(); }
1
2
3
4
5完整代码
import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; void main(List<String> args) { runApp(const BannerWidget()); } // 无状态组件 const img1 = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg-blog.csdnimg.cn%2Fimg_convert%2Fa092a42776106d7e76e867d590b971f0.png&refer=http%3A%2F%2Fimg-blog.csdnimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1671269160&t=c20102eb0a87d3fd49f9a4b3776daedd"; const img2 = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.zhimg.com%2Fv2-3b345224fce3c12bf0a822aa488ae2fc_1440w.jpg%3Fsource%3D172ae18b&refer=http%3A%2F%2Fpic1.zhimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1671270631&t=53cd2791f93fd3038012614d1c5e99ce"; // 有状态组件就像一个舞台,舞台上都是无状态组件 class BannerWidget extends StatefulWidget { const BannerWidget({Key? key}) : super(key: key); State<BannerWidget> createState() => _BannerWidgetState(); } class _BannerWidgetState extends State<BannerWidget> { String imgUrl = ''; // 初始 State, mounted 等于 true, 只执行 1 次 void initState() { // TODO: implement initState super.initState(); imgUrl = img1; print('initState'); // 渲染结束回调,只执行 1 次 SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { print('SchedulerBinding'); print(timeStamp); }); } // 父或祖先 widget 中的 InheritedWidget 改变时会被调用 void didChangeDependencies() { // TODO: implement didChangeDependencies super.didChangeDependencies(); print('didChangeDependencies'); } void didUpdateWidget(covariant BannerWidget oldWidget) { // TODO: implement didUpdateWidget super.didUpdateWidget(oldWidget); print('didUpdateWidget'); } Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('无状态')), body: Column( children: [ ElevatedButton( onPressed: () { if (mounted == true) { setState(() { imgUrl = imgUrl == img1 ? img2 : img1; }); } }, child: const Text("切换图片"), ), Text(imgUrl) ], ), ), ); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
StatelessWidget 生命周期
无状态组件,不需要处理生命周期,直接显示即可,在源码中可见 createElement() 创建组件到组件树,不需要重写去维护。
# APP生命周期
APP生命周期以混入方式 WidgetsBindingObserver
class _BannerWidgetState extends State<BannerWidget> with WidgetsBindingObserver { }
1
2
3需要在
initState
中添加观察者void initState() { // TODO: implement initState super.initState(); // 注入观察者 WidgetsBinding.instance?.addObserver(this); }
1
2
3
4
5
6
7
8生命周期发生回调时
didChangeAppLifecycleState
// 生命周期变化时回调 void didChangeAppLifecycleState(AppLifecycleState state) { // TODO: implement didChangeAppLifecycleState super.didChangeAppLifecycleState(state); print(didChangeAppLifecycleState); }
1
2
3
4
5
6
7销毁观察者
removeObserver
void dispose() { super.dispose(); WidgetsBinding.instance?.removeObserver(this); //销毁观察者 }
1
2
3
4
5名称 说明 resumed 应用程序可见且响应用户输入。 inactive 应用程序处于非激活状态,无法响应用户输入。 pause 应用程序不可见且无法响应用户输入,运行在后台。 detached 应用程序仍寄存在 Flutter 引擎上,但与平台 View 分离。 suspending 应用被挂起,此状态 IOS 永远不会回调 didChangeAccessibilityFeatures
当前系统改变了一些访问性活动的回调void didChangeAccessibilityFeatures() { super.didChangeAccessibilityFeatures(); print("didChangeAccessibilityFeatures"); }
1
2
3
4
5didHaveMemoryPressure
低内存回调void didHaveMemoryPressure() { super.didHaveMemoryPressure(); print("didHaveMemoryPressure"); }
1
2
3
4
5didChangeLocales
用户本地设置变化时调用,如系统语言改变void didChangeLocales(List<Locale>? locale) { super.didChangeLocales(locale); print("didChangeLocales"); }
1
2
3
4
5didChangeMetrics
应用尺寸改变时回调,例如旋转void didChangeMetrics() { super.didChangeMetrics(); Size? size = WidgetsBinding.instance?.window.physicalSize; print("didChangeMetrics :宽:${size?.width} 高:${size?.height}"); }
1
2
3
4
5
6didChangePlatformBrightness
系统切换主题时回调void didChangePlatformBrightness() { super.didChangePlatformBrightness(); print("didChangePlatformBrightness"); }
1
2
3
4
5didChangeTextScaleFactor
文字系数变化void didChangeTextScaleFactor() { super.didChangeTextScaleFactor(); print( "didChangeTextScaleFactor :${WidgetsBinding.instance?.window.textScaleFactor}"); }
1
2
3
4
5
6