前言
在做移动端开发时,不论是安卓的Activity还是iOS的UIViewController都有自己的生命周期,同理Flutter也有自己的生命周期,今天我们就通过以下几个方面来探索一下:
- 1.生命周期的基本概念
- 2.
Widget的生命周期 - 3.
Flutter渲染原理
1.生命周期的基本概念

1.1什么是生命周期
- 1.说白了就是回调函数
- 2.让你知道封装好的这个
Widget处于什么样的状态
1.2生命周期的作用
1.初始化数据
1.1创建变量、常量
1.2发送网络请求2.监听小部件的事件
3.管理内存
3.1销毁数据、销毁监听者
3.2销毁Timer等等
2.Widget的生命周期
2.1StatelessWidget的生命周期
class MyWidget extends StatelessWidget {
const MyWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
}
- 1.构造方法
- 2.build方法
对于StatelessWidget来说,生命周期只有构造和build过程。build是用来创建Widget的,在每次页面刷新时会调用build
2.2StatefulWidget的生命周期
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({Key? key, required this.title}) : super(key: key) {
print('Widget构造方法来了');
}
@override
State<MyHomePage> createState() {
print('Widget的createState方法调用了');
return _MyHomePageState();
}
}
class _MyHomePageState extends State<MyHomePage> {
_MyHomePageState() {
print('State构造方法来了');
}
@override
void initState() {
print('State的initState来了');
super.initState();
}
@override
void didChangeDependencies() {
print('State的didChangeDependencies来了');
super.didChangeDependencies();
}
int _count = 0;
@override
Widget build(BuildContext context) {
print('State的build来了');
return Container(
child: Column(
children: [
ElevatedButton(
onPressed: () {
_count++;
setState(() {});
},
child: const Icon(Icons.add),
),
Text('$_count'),
],
),
);
}
@override
void dispose() {
print('State的dispose来了');
super.dispose();
}
}
- 1.
Widget构造方法 - 2.
Widget的CreateState - 3.
State构造方法 - 4.
State的initState - 5.
didChangeDependencies方法(改变依赖关系);依赖(共享数据)的InheritedWidget发生变化之后,didChangeDependencies才会调用 - 6.
State的Build,当调用setState方法。会重新调用Build进行渲染,setState方法内部主要是利用_element(本质是就是context对象) 调用markNeedsBuild - 7.当
Widget销毁的时候调用State的dispose
2.3setState实现
@protected
void setState(VoidCallback fn) {
assert(fn != null);
assert(() {
if (_debugLifecycleState == _StateLifecycle.defunct) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('setState() called after dispose(): $this'),
ErrorDescription(
'This error happens if you call setState() on a State object for a widget that '
'no longer appears in the widget tree (e.g., whose parent widget no longer '
'includes the widget in its build). This error can occur when code calls '
'setState() from a timer or an animation callback.',
),
ErrorHint(
'The preferred solution is '
'to cancel the timer or stop listening to the animation in the dispose() '
'callback. Another solution is to check the "mounted" property of this '
'object before calling setState() to ensure the object is still in the '
'tree.',
),
ErrorHint(
'This error might indicate a memory leak if setState() is being called '
'because another object is retaining a reference to this State object '
'after it has been removed from the tree. To avoid memory leaks, '
'consider breaking the reference to this object during dispose().',
),
]);
}
if (_debugLifecycleState == _StateLifecycle.created && !mounted) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('setState() called in constructor: $this'),
ErrorHint(
'This happens when you call setState() on a State object for a widget that '
"hasn't been inserted into the widget tree yet. It is not necessary to call "
'setState() in the constructor, since the state is already assumed to be dirty '
'when it is initially created.',
),
]);
}
return true;
}());
final Object? result = fn() as dynamic;
assert(() {
if (result is Future) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('setState() callback argument returned a Future.'),
ErrorDescription(
'The setState() method on $this was called with a closure or method that '
'returned a Future. Maybe it is marked as "async".',
),
ErrorHint(
'Instead of performing asynchronous work inside a call to setState(), first '
'execute the work (without updating the widget state), and then synchronously '
'update the state inside a call to setState().',
),
]);
}
// We ignore other types of return values so that you can do things like:
// setState(() => x = 3);
return true;
}());
_element!.markNeedsBuild();
}
setState方法其实核心就是最后一句_element!.markNeedsBuild();
BuildContext get context {
assert(() {
if (_element == null) {
throw FlutterError(
'This widget has been unmounted, so the State no longer has a context (and should be considered defunct). \n'
'Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.',
);
}
return true;
}());
return _element!;
}
StatefulElement? _element;
由上面的源码可以得出_element其实就是State的bulid方法中的context
3.Flutter渲染原理
实际上,Flutter的UI绘制包含了三个元素,Widget,Element和RenderObject。这三个元素分别组成了三棵树:Widget 树,Element 树和 RenderObject树,在Flutter渲染的流程中Flutter引擎渲染是针对Render树中的对象进行渲染

系统启动时,runApp方法会被调用,Flutter会从最外层的Widget去遍历创建一颗Widget树;
- 每一个
Widget创建出来都会调用createElement方法创建一个Element对象 -
Element加入到Element树中,形成Element树 -
Element通过mount方法调用createRenderObject创建RenderObject对象,并形成相应的RenderObject树
StatelessElement 继承 ComponentElement主要调用build方法,并且将自己(Element)传递出去
StatefulElement 继承 ComponentElement,调用creatState方法,创建state,将Widget赋值给State对象,调用state的build方法,并且将自己(Element)传出去
⚠️注意
只有继承自RenderObjectWidget的Widget才能创建RenderObject并加入RenderObject树,被渲染
3.1三棵树的作用
-
Widget树:配置信息,用来描述UI特征,比如尺寸多大,颜色是什么,位置在哪里 -
Element树:element是widget的实际实例,它同时持有了widget和renderObject的引用,用来决定是否进行UI更新。 -
RenderObject树:UI更新的执行者,保存了元素的大小,布局等信息。它才是真正调用渲染引擎去进行更新的对象