Flutter的生命周期

Posted 小图包

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter的生命周期相关的知识,希望对你有一定的参考价值。

生命周期是一个从创建到销毁的过程,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对象从树中被永久移除时调用;通常在此回调中释放资源。

生命周期图如下

 

示例如下

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 生命周期
 

点击父组件setState的生命周期

点击子组件的生命周期

进入page2 的生命周期

退出page2 的生命周期

点击热重载按钮的生命周期

二、 App的生命周期

App的生命周期需要通过WidgetsBindingObserver的didChangeAppLifecycleState来获取,在initState中添加监听WidgetsBinding.instance.addObserver(this);

resumed:可见并能响应用户的输入
inactive:处在并不活动状态,无法处理用户响应
paused:不可见并不能响应用户的输入,但是在后台继续活动


app从前台退到后台的生命周期

app 从后台回到前台的生命周期

退出app的生命周期

 

以上是关于Flutter的生命周期的主要内容,如果未能解决你的问题,请参考以下文章

在不存在的片段上调用片段生命周期和 onCreate 的问题

Android片段生命周期:onResume调用了两次

导航上的片段生命周期重叠

Flutter 没有完整的生命周期?

Flutter 没有完整的生命周期?

Flutter 没有完整的生命周期?