一、State生命周期介紹
Flutter中一切皆widget挑格。widget分為無狀態(tài)和有狀態(tài)兩種咙冗,分別是StatelessWidget和StatefulWidget。無狀態(tài)組件只加載一次漂彤,無生命周期雾消。有狀態(tài)組件可以根據(jù)數(shù)據(jù)來更新灾搏,下面介紹一下有狀態(tài)組件的生命周期。
Flutter的生命周期包含一下幾個(gè)階段:
- CreateState 該函數(shù)為StatefulWidget創(chuàng)建State時(shí)調(diào)用的方法仪或,當(dāng)StatefulWidget被調(diào)用時(shí)候會(huì)立即調(diào)用此方法确镊。
- initState 該方法為State初始化調(diào)用,因此在此期間可以執(zhí)行變量的初始化范删,還可以進(jìn)行與服務(wù)端的初始化蕾域,獲取到服務(wù)端數(shù)據(jù)之后調(diào)用setState方法更新組件。
- didChangeDependencies 該函數(shù)是在該組件依賴的全局State發(fā)生變化的時(shí)候調(diào)用到旦。
- build 該函數(shù)主要是渲染W(wǎng)idget旨巷,會(huì)被調(diào)用多次,最好只做返回Widget相關(guān)的事情添忘。
- reassemble 只要是提供開發(fā)階段使用采呐,只有在debug模式下熱重載才會(huì)調(diào)用「槠铮可以添加一些代碼來調(diào)試斧吐。
- didUpdateWidget 此方法在組件重新構(gòu)建,比如熱更新仲器,父組件發(fā)生Build時(shí)候調(diào)用此方法煤率,其次此方法會(huì)導(dǎo)致本組件的build方法被調(diào)用。
-
deactivate 在組件被移除時(shí)候調(diào)用乏冀,如果組件被移除蝶糯,未被插入到其他組件。那么會(huì)調(diào)用dispose永久移除辆沦。
flutter生命周期.png
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Lifecycle extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'lifecycle',
home: Scaffold(
appBar: AppBar(
title: Text('lifecyle'),
),
body: Center(
child: LifecycleWidget(),
),
),
);
}
}
class LifecycleWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
print('createState');
return LifecycleState();
}
}
class LifecycleState extends State<LifecycleWidget> {
int count = 1;
String name = 'test';
@override
void initState() {
print('initState');
super.initState();
}
@override
void didChangeDependencies() {
print('didchangeDependencies');
super.didChangeDependencies();
}
@override
void didUpdateWidget(LifecycleWidget oldWidget) {
count++;
print('didUpdateWidge $count');
super.didUpdateWidget(oldWidget);
}
@override
void deactivate() {
print('deactivate');
super.deactivate();
}
@override
void dispose() {
print('dispose');
super.dispose();
}
@override
void reassemble() {
print('reassemble');
super.reassemble();
}
void changeName(){
setState(() {
print('set State');
this.name = 'flutter';
});
}
@override
Widget build(BuildContext context) {
print('buid');
return Column(
children: <Widget>[
FlatButton(
child: Text('$name $count'),
onPressed: changeName,
)
],
);
}
}
打印結(jié)果
I/flutter ( 1431): createState
I/flutter ( 1431): initState
I/flutter ( 1431): didchangeDependencies
I/flutter ( 1431): buid
I/flutter ( 1431): reassemble
I/flutter ( 1431): didUpdateWidge 2
I/flutter ( 1431): buid
點(diǎn)擊按鈕
I/flutter ( 1604): set State
I/flutter ( 1604): buid
第一次build了兩次昼捍,正式模式下是不會(huì)這樣的,build很消耗性能的。
setState會(huì)引起build ,而buid會(huì)重新更新組件控妻,并且他的子組件也會(huì)更新蚜印。會(huì)調(diào)用子組件的didUpdateWidget和build方法。
I/flutter ( 1956): set State
I/flutter ( 1956): buid
I/flutter ( 1956): sub didUpdateWidget
I/flutter ( 1956): sub build
二、App生命周期的介紹
app的啟動(dòng)到退出的全過程。在Flutter中可以通過WidgetsBindingObserver來實(shí)現(xiàn)監(jiān)聽。
abstract class WidgetsBindingObserver {
//頁面pop
Future<bool> didPopRoute() => Future<bool>.value(false);
//頁面push
Future<bool> didPushRoute(String route) => Future<bool>.value(false);
//系統(tǒng)窗口相關(guān)改變回調(diào)团赁,如旋轉(zhuǎn)
void didChangeMetrics() { }
//文本縮放系數(shù)變化
void didChangeTextScaleFactor() { }
//系統(tǒng)亮度變化
void didChangePlatformBrightness() { }
//本地化語言變化
void didChangeLocales(List<Locale> locale) { }
//App生命周期變化
void didChangeAppLifecycleState(AppLifecycleState state) { }
//內(nèi)存警告回調(diào)
void didHaveMemoryPressure() { }
//Accessibility相關(guān)特性回調(diào)
void didChangeAccessibilityFeatures() {}
}
重點(diǎn)介紹下didChangeAppLifecycleState這個(gè)回調(diào)方法。
AppLifecycleState是個(gè)枚舉谨履,有三個(gè)狀態(tài):
- resume 可見欢摄,能響應(yīng)操作
- inactive 處于不可活動(dòng)狀態(tài),無法處理用戶響應(yīng)
- paused 不可見笋粟,不能響應(yīng)用戶輸入怀挠,但在后臺(tái)繼續(xù)活動(dòng)中析蝴。
寫一個(gè)demo測(cè)試一下打印
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver{//這里你可以再回顧下,第7篇文章“函數(shù)绿淋、類與運(yùn)算符:Dart是如何處理信息的闷畸?”中關(guān)于Mixin的內(nèi)容
...
@override
@mustCallSuper
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);//注冊(cè)監(jiān)聽器
}
@override
@mustCallSuper
void dispose(){
super.dispose();
WidgetsBinding.instance.removeObserver(this);//移除監(jiān)聽器
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) async {
print("$state");
if (state == AppLifecycleState.resumed) {
//do sth
}
}
}
我們?cè)囍袚Q一下前、后臺(tái)吞滞,觀察控制臺(tái)輸出的 App 狀態(tài)佑菩,可以發(fā)現(xiàn):從后臺(tái)切入前臺(tái),控制臺(tái)打印的 App 生命周期變化如下: AppLifecycleState.paused->AppLifecycleState.inactive->AppLifecycleState.resumed裁赠;從前臺(tái)退回后臺(tái)殿漠,控制臺(tái)打印的 App 生命周期變化則變成了:AppLifecycleState.resumed->AppLifecycleState.inactive->AppLifecycleState.paused∨謇蹋可以看到绞幌,App 前后臺(tái)切換過程中打印出的狀態(tài)是完全符合預(yù)期的。
三一忱、幀繪制回調(diào)
以安卓為例莲蜘,有時(shí)候我們需要使用view.post等待渲染完成之后去做一些操作。
在flutter中帘营,可以監(jiān)聽幀的回調(diào)菇夸,有兩種:一種是只回調(diào)一次,一種是每一幀都回調(diào)仪吧。
- 單幀回調(diào):通過addPostFrameCallback回調(diào)來監(jiān)聽當(dāng)前幀繪制完成
WidgetsBinding.instance.addPostFrameCallback((_){
print("單次Frame繪制回調(diào)");//只回調(diào)一次
});
- 多幀回調(diào):通過addPersistentFrameCallback回調(diào)監(jiān)聽每一次幀繪制完成的回調(diào),可以用來做幀的檢測(cè)鞠眉。
WidgetsBinding.instance.addPersistentFrameCallback((_){
print("實(shí)時(shí)Frame繪制回調(diào)");//每幀都回調(diào)
});