Flutter視圖Widget生命週期

Flutter視圖Widget生命週期

做爲一個Android開發者,必定會對Activity的生命週期有這很深入的印象,而當你在使用Flutter時,其中Widget就是View,其生命週期就是從View建立到銷燬的過程。 Widget分爲StatelessWidgetStatefulWidget 兩種,這兩種Widget的生命週期分別以下。bash

StatelessWidget的生命週期

無狀態Widget的生命週期很簡單,它只有一個生命週期:build網絡

build

build函數用來構建視圖,每次頁面刷新是被調用,典型的用法以下:app

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(
          child: new Text('Hello World'),
        ),
      ),
    );
  }
}
複製代碼

StatefulWidget的生命週期

StatefulWidget生命週期整理以下圖:less

大體可分爲三個階段:

  • 初始化:插入渲染樹
  • 運行中:在渲染樹中存在
  • 銷燬:從渲染樹中移除
初始化階段
createState

createState必須且僅執行一次,它用來建立state,當建立StatefulWidget時,該放方法被執行ide

initState

在建立StatefulWidget後,initState是第一個被調用的方法,同createState同樣只被調用一次,此時widget的被添加至渲染樹,mount的值會變爲true,但並無渲染。能夠在該方法內作一些初始化操做。在在override時要低啊用super.initState()函數

@override
void initState() {
  super.initState();
  ...
}
複製代碼
didChangeDependencies

當widget第一次被建立時,didChangeDependencies緊跟着initState函數以後調用,在widget刷新時,該方法不會被調用。它會在「依賴」發生變化時被Flutter Framework調用,這個依賴是指widget是否使用父widget中InheritedWidget的數據。也便是隻有在widget依賴的InheritedWidget發生變化以後,didChangeDependencies纔會調用。 這種機制可使子組件在所依賴的InheritedWidget變化時來更新自身!好比當主題、locale(語言)等發生變化時,依賴其的子widget的didChangeDependencies方法將會被調用。ui

//經過繼承InheritedWidget,將當前計數器點擊次數保存在ShareDataWidget的data屬性中:
class ShareDataWidget extends InheritedWidget {
  ShareDataWidget({
    @required this.data,
    Widget child
  }) :super(child: child);

  final int data; //須要在子樹中共享的數據,保存點擊次數

  //定義一個便捷方法,方便子樹中的widget獲取共享數據  
  static ShareDataWidget of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(ShareDataWidget);
  }

  //該回調決定當data發生變化時,是否通知子樹中依賴data的Widget  
  @override
  bool updateShouldNotify(ShareDataWidget old) {
    //若是返回true,則子樹中依賴(build函數中有調用)本widget
    //的子widget的`state.didChangeDependencies`會被調用
    return old.data != data;
  }
}

class _TestWidget extends StatefulWidget {
  @override
  __TestWidgetState createState() => new __TestWidgetState();
}
//而後咱們實現一個子組件_TestWidget,在其build方法中引用ShareDataWidget中的數據。
class __TestWidgetState extends State<_TestWidget> {
  @override
  Widget build(BuildContext context) {
    //使用InheritedWidget中的共享數據
    return Text(ShareDataWidget
        .of(context)
        .data
        .toString());
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    //父或祖先widget中的InheritedWidget改變(updateShouldNotify返回true)時會被調用。
    //若是build中沒有依賴InheritedWidget,則此回調不會被調用。
    print("Dependencies change");
  }
}

複製代碼

注意:若是_TestWidget的build方法中沒有使用ShareDataWidget的數據,那麼它的didChangeDependencies()將不會被調用,由於它並無依賴ShareDataWidget。在依賴改變以後build方法也會被調用,因此在大多數場景下都無需使用didChangeDependencies。然而若是你須要在依賴改變後執行一些昂貴的操做,好比網絡請求,這時最好的方式就是在此方法中執行,這樣能夠避免每次build()都執行這些昂貴操做。this

build

build函數會在widget第一次建立時緊跟着didChangeDependencies方法以後和UI從新渲染是時調用。build只作widget的建立操做,若是在build裏作其餘操做,會影響UI的渲染效果spa

運行中
didUpdateWidget

當組件的狀態改變的時候就會調用didUpdateWidget,好比調用了setState.code

銷燬
deactivate

當要將State對象從渲染樹中移除的時候,就會調用 deactivate 生命週期,這標誌着 StatefulWidget將要銷燬。頁面切換時,也會調用它,由於此時State在視圖樹中的位置發生了變化可是State不會被銷燬,而是從新插入到渲染樹中。 重寫的時候必需要調用 super.deactivate()

dispose

從渲染樹中移除view的時候調用,State會永久的從渲染樹中移除,和initState正好相反mount值變味false。這時候就能夠在dispose裏作一些取消監聽操做。

總結:
函數 調用次數 調用時間
createState 1 第一次建立
initState 1 第一次建立
didChangeDependencies n 第一次建立和依賴變化時
build n 第一次建立和UI從新渲染時
didUpdateWidget n 第一次建立和UI從新渲染時
deactivate n state對象將要移除時
dispose 1 state對象移除
相關文章
相關標籤/搜索