前言
在做移動(dòng)端開(kāi)發(fā)時(shí),不論是安卓的Activity還是iOS的UIViewController都有自己的生命周期,同理Flutter也有自己的生命周期,今天我們就通過(guò)以下幾個(gè)方面來(lái)探索一下:
- 1.生命周期的基本概念
- 2.
Widget的生命周期 - 3.
Flutter渲染原理
1.生命周期的基本概念

1.1什么是生命周期
- 1.說(shuō)白了就是回調(diào)函數(shù)
- 2.讓你知道封裝好的這個(gè)
Widget處于什么樣的狀態(tài)
1.2生命周期的作用
1.初始化數(shù)據(jù)
1.1創(chuàng)建變量、常量
1.2發(fā)送網(wǎng)絡(luò)請(qǐng)求2.監(jiān)聽(tīng)小部件的事件
3.管理內(nèi)存
3.1銷毀數(shù)據(jù)、銷毀監(jiān)聽(tīng)者
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.構(gòu)造方法
- 2.build方法
對(duì)于StatelessWidget來(lái)說(shuō),生命周期只有構(gòu)造和build過(guò)程。build是用來(lái)創(chuàng)建Widget的,在每次頁(yè)面刷新時(shí)會(huì)調(diào)用build
2.2StatefulWidget的生命周期
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({Key? key, required this.title}) : super(key: key) {
print('Widget構(gòu)造方法來(lái)了');
}
@override
State<MyHomePage> createState() {
print('Widget的createState方法調(diào)用了');
return _MyHomePageState();
}
}
class _MyHomePageState extends State<MyHomePage> {
_MyHomePageState() {
print('State構(gòu)造方法來(lái)了');
}
@override
void initState() {
print('State的initState來(lái)了');
super.initState();
}
@override
void didChangeDependencies() {
print('State的didChangeDependencies來(lái)了');
super.didChangeDependencies();
}
int _count = 0;
@override
Widget build(BuildContext context) {
print('State的build來(lái)了');
return Container(
child: Column(
children: [
ElevatedButton(
onPressed: () {
_count++;
setState(() {});
},
child: const Icon(Icons.add),
),
Text('$_count'),
],
),
);
}
@override
void dispose() {
print('State的dispose來(lái)了');
super.dispose();
}
}
- 1.
Widget構(gòu)造方法 - 2.
Widget的CreateState - 3.
State構(gòu)造方法 - 4.
State的initState - 5.
didChangeDependencies方法(改變依賴關(guān)系);依賴(共享數(shù)據(jù))的InheritedWidget發(fā)生變化之后,didChangeDependencies才會(huì)調(diào)用 - 6.
State的Build,當(dāng)調(diào)用setState方法。會(huì)重新調(diào)用Build進(jìn)行渲染,setState方法內(nèi)部主要是利用_element(本質(zhì)是就是context對(duì)象) 調(diào)用markNeedsBuild - 7.當(dāng)
Widget銷毀的時(shí)候調(diào)用State的dispose
2.3setState實(shí)現(xiàn)
@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方法其實(shí)核心就是最后一句_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其實(shí)就是State的bulid方法中的context
3.Flutter渲染原理
實(shí)際上,Flutter的UI繪制包含了三個(gè)元素,Widget,Element和RenderObject。這三個(gè)元素分別組成了三棵樹(shù):Widget 樹(shù),Element 樹(shù)和 RenderObject樹(shù),在Flutter渲染的流程中Flutter引擎渲染是針對(duì)Render樹(shù)中的對(duì)象進(jìn)行渲染

系統(tǒng)啟動(dòng)時(shí),runApp方法會(huì)被調(diào)用,Flutter會(huì)從最外層的Widget去遍歷創(chuàng)建一顆Widget樹(shù);
- 每一個(gè)
Widget創(chuàng)建出來(lái)都會(huì)調(diào)用createElement方法創(chuàng)建一個(gè)Element對(duì)象 -
Element加入到Element樹(shù)中,形成Element樹(shù) -
Element通過(guò)mount方法調(diào)用createRenderObject創(chuàng)建RenderObject對(duì)象,并形成相應(yīng)的RenderObject樹(shù)
StatelessElement 繼承 ComponentElement主要調(diào)用build方法,并且將自己(Element)傳遞出去
StatefulElement 繼承 ComponentElement,調(diào)用creatState方法,創(chuàng)建state,將Widget賦值給State對(duì)象,調(diào)用state的build方法,并且將自己(Element)傳出去
??注意
只有繼承自RenderObjectWidget的Widget才能創(chuàng)建RenderObject并加入RenderObject樹(shù),被渲染
3.1三棵樹(shù)的作用
-
Widget樹(shù):配置信息,用來(lái)描述UI特征,比如尺寸多大,顏色是什么,位置在哪里 -
Element樹(shù):element是widget的實(shí)際實(shí)例,它同時(shí)持有了widget和renderObject的引用,用來(lái)決定是否進(jìn)行UI更新。 -
RenderObject樹(shù):UI更新的執(zhí)行者,保存了元素的大小,布局等信息。它才是真正調(diào)用渲染引擎去進(jìn)行更新的對(duì)象