1. StatefulWidget
1.1. 認識StatefulWidget
在Flutter開發(fā)中,所有的widget都不能定義狀態(tài);
注意:widget是@immutable 修飾的,所以繼承wedget的類內(nèi)部是不能寫變量的,只能用final修飾;
? 創(chuàng)建一個單獨的類,負責維護狀態(tài);
為什么 ?
? 這次因為Flutter在設計的時候就決定了一旦Widget中展示的數(shù)據(jù)發(fā)生變化,就重新構建整個Widget;
? Flutter通過一些機制來限定定義到Widget中的成員變量必須是final的;
為什么Flutter在設計的時候,StatefulWidget的build方法放在State中 ?
? 1. build出來的widget是需要依賴State中的變量(狀態(tài)、數(shù)據(jù));
? 2. 在flutter的運行過程中:
? widget是不斷銷毀和創(chuàng)建的;
? 當我們自己的狀態(tài)發(fā)生改變時,并不希望創(chuàng)建一個新的state;
1.2. 案例展示

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: YZHomePage()
);
}
}
class YZHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("商品列表")
),
body: YZHomeContent("你好,李煥英")
);
}
}
class YZHomeContent extends StatefulWidget {
final String message;
YZHomeContent(this.message);
@override
_YZHomeContentState createState() => _YZHomeContentState();
}
class _YZHomeContentState extends State<YZHomeContent> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_getButtons(),
Text("當前計數(shù):$_counter", style: TextStyle(fontSize: 25),),
Text("傳遞過來的信息:${widget.message}")
],
),
);
}
Widget _getButtons(){
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
RaisedButton(
child: Text("+", style: TextStyle(fontSize: 20, color: Colors.white)),
color: Colors.pink,
onPressed: () {
setState(() {
_counter++;
});
}
),
RaisedButton(
child: Text("-", style: TextStyle(fontSize: 20, color: Colors.white)),
color: Colors.purple,
onPressed: () {
setState(() {
_counter--;
});
}
)
],
);
}
}
1.3. StatefulWidget 的生命周期
1.3.1. 生命周期的理解
什么是生命周期呢?
客戶端開發(fā):iOS開發(fā)中我們需要知道UIViewController從創(chuàng)建到銷毀的整個過程,Android開發(fā)中我們需要知道Activity從創(chuàng)建到銷毀的整個過程。以便在不同的生命周期方法中完成不同的操作;
前端開發(fā)中:Vue、React開發(fā)中組件也都有自己的生命周期,在不同的生命周期中我們可以做不同的操作;
Flutter小部件的生命周期:
StatelessWidget可以由父Widget直接傳入值,調(diào)用build方法來構建,整個過程非常簡單;
class YZHomeContent extends StatelessWidget {
final Sting message;
YZHomeContent(this.message) {
print("構造函數(shù)被調(diào)用");
}
@override
Widget build(BuildContext context) {
print("調(diào)用build方法");
return Text(message);
}
}
而StatefulWidget需要通過State來管理其數(shù)據(jù),并且還要監(jiān)控狀態(tài)的改變決定是否重新build整個Widget;
所以,我們主要討論StatefulWidget的生命周期,也就是它從創(chuàng)建到銷毀的整個過程;
1.3.2. StatefulWidget生命周期簡單版
class YZhomeContent extends StatefulWidget {
@override
_YZhomeContentState createState() => _YZhomeContentState();
}
class _YZhomeContentState extends State<YZhomeContent> {
@override
Widget build(BuildContext context) {
return Container(
);
}
}
由上面代碼中,我們知道StatefulWidget本身由兩個類組成:StatefulWidget和State;

首先,執(zhí)行StatefulWidget中相關的方法:
- 執(zhí)行
StatefulWidget的構造函數(shù)(Constructor)來創(chuàng)建出StatefulWidget;
- 執(zhí)行
- 執(zhí)行
StatefulWidget的createState方法,來創(chuàng)建一個維護StatefulWidget的State對象;
其次,調(diào)用createState創(chuàng)建State對象時,執(zhí)行State類相關方法;
- 執(zhí)行
- 執(zhí)行
State類的構造方法(Constructor)來創(chuàng)建State對象;
- 執(zhí)行
- 執(zhí)行
ininState,我們通常會在這個方法中執(zhí)行一些數(shù)據(jù)初始化的操作,或者也可能會發(fā)送網(wǎng)絡請求;
- 執(zhí)行
@protected
@mustCallSuper
void initState() {
assert(_debugLifecycleState == _StateLifecycle.created);
}
注意:這個方法是重寫父類的方法,必須調(diào)用super,因為父類中會進行一些其他操作;
并且如果你閱讀源碼,你會發(fā)現(xiàn)這里有一個注解(annotation):@mustCallSuper
-
執(zhí)行
didChangeDependencies方法,這個方法在兩種情況下會調(diào)用- 情況一:調(diào)用
initState會調(diào)用; - 情況二:從其他對象中依賴一些數(shù)據(jù)發(fā)生改變時,比如前面我們提到的
InheritedWidget;
- 情況一:調(diào)用
-
- Flutter執(zhí)行build方法,來看一下我們當前的Widget需要渲染哪些Widget;
- 當前的Widget不再使用時,會調(diào)用
dispose進行銷毀;
- 當前的Widget不再使用時,會調(diào)用
- 手動調(diào)用
setState方法,會根據(jù)最新的狀態(tài)(數(shù)據(jù))來重新調(diào)用build方法,構建對應的Widgets;
- 手動調(diào)用
- 執(zhí)行
didUpdateWidget方法是在當父Widget觸發(fā)重建(rebuild)時,系統(tǒng)會調(diào)用didUpdateWidget方法;
- 執(zhí)行
class YZHomeContent extends StatefulWidget {
YZHomeContent(){
print("1.調(diào)用YZHomeContent的construction方法");
}
@override
_YZHomeContentState createState() {
print("2.調(diào)用YZHomeContent的createState方法");
return _YZHomeContentState();
};
}
class _YZHomeContentState extends State<YZHomeContent> {
_YZHomeContentState() {
print("3.調(diào)用YZHomeContentState的construction方法");
}
@override
void initState() {
// TODO: implement initState
super.initState();
print("4.調(diào)用_YZHomeContentState的initState方法");
}
@override
Widget build(BuildContext context) {
print("5.調(diào)用_YZHomeContentState的build");
return Container();
}
@override
void dispose() {
// TODO: implement dispose
print("6.調(diào)用_YZHomeContentState的dispose");
super.dispose();
}
}
1.3.3. 生命周期的復雜版
- mounted是State內(nèi)部設置的一個屬性,事實上我們不了解它也可以,但是如果你想深入了解它,會對State的機制理解更加清晰;
- 是內(nèi)部設置的,不需要我們手動進行修改;
- dirty state的含義是臟的State
它實際是通過一個Element的東西的屬性來標記的;
將它標記為dirty會等待下一次的重繪檢查,強制調(diào)用build方法來構建我們的Widget;
- clean state的含義是干凈的State
- 它表示當前build出來的Widget,下一次重繪檢查時不需要重新build;