前言
在做移動端開發(fā)時习柠,不論是安卓的Activity
還是iOS的UIViewController
都有自己的生命周期喳坠,同理Flutter
也有自己的生命周期构回,今天我們就通過以下幾個方面來探索一下:
- 1.生命周期的基本概念
- 2.
Widget
的生命周期 - 3.
Flutter
渲染原理
1.生命周期的基本概念
1.1什么是生命周期
- 1.說白了就是回調(diào)函數(shù)
- 2.讓你知道封裝好的這個
Widget
處于什么樣的狀態(tài)
1.2生命周期的作用
1.初始化數(shù)據(jù)
1.1創(chuàng)建變量谷炸、常量
1.2發(fā)送網(wǎng)絡(luò)請求2.監(jiān)聽小部件的事件
3.管理內(nèi)存
3.1銷毀數(shù)據(jù)、銷毀監(jiān)聽者
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方法
對于StatelessWidget
來說畦徘,生命周期只有構(gòu)造和build
過程毕籽。build是用來創(chuàng)建Widget
的,在每次頁面刷新時會調(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)造方法來了');
}
@override
State<MyHomePage> createState() {
print('Widget的createState方法調(diào)用了');
return _MyHomePageState();
}
}
class _MyHomePageState extends State<MyHomePage> {
_MyHomePageState() {
print('State構(gòu)造方法來了');
}
@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
構(gòu)造方法 - 2.
Widget
的CreateState
- 3.
State
構(gòu)造方法 - 4.
State
的initState
- 5.
didChangeDependencies
方法(改變依賴關(guān)系);依賴(共享數(shù)據(jù))的InheritedWidget
發(fā)生變化之后井辆,didChangeDependencies
才會調(diào)用 - 6.
State
的Build
,當(dāng)調(diào)用setState
方法关筒。會重新調(diào)用Build進(jìn)行渲染,setState
方法內(nèi)部主要是利用_element
(本質(zhì)是就是context
對象) 調(diào)用markNeedsBuild
- 7.當(dāng)
Widget
銷毀的時候調(diào)用State
的dispose
2.3setState
實現(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
方法其實核心就是最后一句_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
樹中的對象進(jìn)行渲染
系統(tǒng)啟動時袍榆,runApp方法會被調(diào)用胀屿,Flutter
會從最外層的Widget
去遍歷創(chuàng)建一顆Widget
樹;
- 每一個
Widget
創(chuàng)建出來都會調(diào)用createElement
方法創(chuàng)建一個Element
對象 -
Element
加入到Element
樹中包雀,形成Element
樹 -
Element
通過mount
方法調(diào)用createRenderObject
創(chuàng)建RenderObject
對象,并形成相應(yīng)的RenderObject
樹
StatelessElement
繼承 ComponentElement
主要調(diào)用build
方法宿崭,并且將自己(Element
)傳遞出去
StatefulElement
繼承 ComponentElement
,調(diào)用creatState
方法,創(chuàng)建state
,將Widget
賦值給State
對象,調(diào)用state
的build
方法才写,并且將自己(Element
)傳出去
??注意
只有繼承自RenderObjectWidget
的Widget
才能創(chuàng)建RenderObject
并加入RenderObject
樹劳曹,被渲染
3.1三棵樹的作用
-
Widget
樹:配置信息,用來描述UI特征琅摩,比如尺寸多大,顏色是什么锭硼,位置在哪里 -
Element
樹:element是widget的實際實例房资,它同時持有了widget和renderObject的引用,用來決定是否進(jìn)行UI更新檀头。 -
RenderObject
樹:UI更新的執(zhí)行者轰异,保存了元素的大小,布局等信息暑始。它才是真正調(diào)用渲染引擎去進(jìn)行更新的對象