天天看點

Flutter的生命周期二、 App的生命周期

生命周期是一個從建立到銷毀的過程,Flutter生命周期分為兩部分:

1.Widget的生命周期

2.APP的生命周期

我們先看Widget的生命周期

一、Widget的生命周期

1.StatelessWidget

對于StatelessWidget來說,生命周期隻有build過程。build是用來建立Widget的,在每次頁面重新整理時會調用build。

2.StatefulWidget

StatefulWidget的生命周期依次為:

initState:當Widget第一次插入到Widget樹時會被調用,對于每一個State對象,這個方法隻會調用一次。是以,通常在該回調中做一些一次性的操作,如一些初始化操作。(注意:不能在該回調中調用BuildContext.inheritFromWidgetOfExactType(該方法用于在Widget樹上擷取離目前widget最近的一個父級InheritFromWidget),原因是在初始化完成後,Widget樹中的InheritFromWidget也可能會發生變化,是以正确的做法應該在在build()方法或didChangeDependencies()中調用它。)

didChangeDependencies():當State對象的依賴發生變化時會被調用;

這個方法在兩種情況下會調用:

情況一:調用initState會調用;

情況二:從其他對象中依賴一些資料發生改變時,比如前面我們提到的InheritedWidget;

build:它主要是用于建構Widget子樹

reassemble:此回調是專門為了開發調試而提供的,在熱重載(hot reload)時會被調用,此回調在Release模式下永遠不會被調用。

didUpdateWidget:在widget重新建構時,Flutter framework會調用Widget.canUpdate來檢測Widget樹中同一位置的新舊節點,然後決定是否需要更新,如果Widget.canUpdate傳回true則會調用此回調。正如之前所述,Widget.canUpdate會在新舊widget的key和runtimeType同時相等時會傳回true,也就是說在在新舊widget的key和runtimeType同時相等時didUpdateWidget()就會被調用。

deactivate:當State對象從樹中被移除時,會調用此回調。在一些場景下,Flutter framework會将State對象重新插到樹中,如包含此State對象的子樹在樹的一個位置移動到另一個位置時(可以通過GlobalKey來實作)。如果移除後沒有重新插入到樹中則緊接着會調用dispose()方法。

dispose:當State對象從樹中被永久移除時調用;通常在此回調中釋放資源。

生命周期圖如下

Flutter的生命周期二、 App的生命周期

示例如下

class Life extends StatefulWidget {
  @override

  _TestLifeState createState() => _TestLifeState();
}


class _TestLifeState extends State<Life>  with WidgetsBindingObserver {
  String title = "點選父元件";

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    print('page1--initState');
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print(state.toString());
  }

  @override
  void didChangeDependencies() {
    print('test-page1--didChangeDependencies');
    super.didChangeDependencies();
  }

  @override
  void didUpdateWidget(Life oldWidget) {
    print('test-page1--didUpdateWidget');
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    print('test-page1--build');
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text("生命周期示例"),
      ),
      body: Column(
        children: <Widget>[
          GestureDetector(
            child: new Text(title ?? ""),
            onTap: () {
              setState(() {
                title = "父元件變化了";
              });
            },
          ),


          Container(
            width: 100,
            height: 50,
            child: Column (children: [

            ],),
          ),
          ChildStatefulWidget(),

          FlatButton(
              color: Colors.grey,
              onPressed: () {
                Navigator.of(context)
                    .push(new MaterialPageRoute(builder: (BuildContext c) {
                  return new TestLifeCyclePage2();
                }));
              },
              child: Text("跳轉頁面")),
        ],
      ),
    );
  }

  @override
  void reassemble() {
    // TODO: implement reassemble
    super.reassemble();
    print('test-page1--reassemble');
  }

  @override
  void deactivate() {
    // TODO: implement deactivate
    super.deactivate();
    print('test-page1--deactivate');
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    //WidgetsBinding.instance.addObserver(this);
    print('test-page1--dispose');
  }
}
           
class ChildStatefulWidget extends StatefulWidget {

  @override
  _ChildStatefulWidgetState createState() {
    print("child--createState");
    return _ChildStatefulWidgetState();
  }
}

class _ChildStatefulWidgetState extends State<ChildStatefulWidget> {
  String title = "點選子元件";

  @override
  Widget build(BuildContext context) {
    print('child--build');
    return GestureDetector(
      child: new Text(title ?? ""),
      onTap: () {
        setState(() {
          title = "子元件變化了";
        });
      },
    );
  }

  @override
  void initState() {
    print('child--initState');
    super.initState();
  }

  @override
  void didChangeDependencies() {
    print('child--didChangeDependencies');
    super.didChangeDependencies();
  }

  @override
  void didUpdateWidget(ChildStatefulWidget oldWidget) {
    print('child--didUpdateWidget');
    super.didUpdateWidget(oldWidget);
  }

  @override
  void reassemble() {
    print('child--reassemble');
    super.reassemble();
  }

  @override
  void deactivate() {
    print('child--deactivate');
    super.deactivate();
  }

  @override
  void dispose() {
    print('child--dispose');
    super.dispose();
    //WidgetsBinding.instance.addObserver(this);
  }
}
           
class TestLifeCyclePage2 extends StatefulWidget {
  @override
  _Test2LifeCyclePageState createState(){
    return new _Test2LifeCyclePageState();
  }

  @override
  StatefulElement createElement() {
    // TODO: implement createElement
//    print("page2--createElement");
    return super.createElement();
  }
}

class _Test2LifeCyclePageState extends State<TestLifeCyclePage2> with WidgetsBindingObserver {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    print('test-page2---initState');
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print(state.toString());
  }

  @override
  void didChangeDependencies() {
    // TODO: implement didChangeDependencies
    super.didChangeDependencies();
    print('test-page2---didChangeDependencies');
  }

  @override
  void didUpdateWidget(TestLifeCyclePage2 oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);
    print('test-page2---didUpdateWidget');
  }

  @override
  Widget build(BuildContext context) {
    print('page2---build');
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text("生命周期示例2"),
      ),
    );
  }

  @override
  void reassemble() {
    // TODO: implement reassemble
    super.reassemble();
    print('test-page2---reassemble');
  }

  @override
  void deactivate() {
    // TODO: implement deactivate
    super.deactivate();
    print('test-page2---deactivate');
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    //WidgetsBinding.instance.addObserver(this);
    print('test-page2---dispose');
  }
}
           

進入page1 生命周期

Flutter的生命周期二、 App的生命周期

點選父元件setState的生命周期

Flutter的生命周期二、 App的生命周期

點選子元件的生命周期

Flutter的生命周期二、 App的生命周期

進入page2 的生命周期

Flutter的生命周期二、 App的生命周期

退出page2 的生命周期

Flutter的生命周期二、 App的生命周期

點選熱重載按鈕的生命周期

Flutter的生命周期二、 App的生命周期

二、 App的生命周期

App的生命周期需要通過WidgetsBindingObserver的didChangeAppLifecycleState來擷取,在initState中添加監聽

WidgetsBinding.instance.addObserver(this);

resumed:可見并能響應使用者的輸入

inactive:處在并不活動狀态,無法處理使用者響應

paused:不可見并不能響應使用者的輸入,但是在背景繼續活動

app從前台退到背景的生命周期

Flutter的生命周期二、 App的生命周期

app 從背景回到前台的生命周期

Flutter的生命周期二、 App的生命周期

退出app的生命周期

Flutter的生命周期二、 App的生命周期