Flutter(Widget和App)的生命周期

Flutter中的widget的刷新主要是靠State来控制,在对应的逻辑中setState()便可达到刷新widget的效果。
在flutter中,常用的widget有两种:

  • StatelessWidget:无状态不需要刷新
  • StatefulWidget:有状态需要通过setState()更新

1.StatelessWidget:

一些创建之后就不会在根据数据或者逻辑再去变更页面的样式的widget,比如:固定的Image、一些不会更改的文本描述等。例如下面的例子:

class TitleWidget extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Container(context);
  }

StatelessWidget的生命周期只有build()一个函数,在build()中返回对应的视图就可以了。


2.StatefulWidget:

根据状态可以进行UI的变更,变更的逻辑是通过修改参数进行UI的变更,且需要在setState(){}包裹

setState((){
    // 更新状态、数据
})

创建一个动态的widget:

class DynamicWidget extends StatefulWidget {
  DynamicWidget({Key key}) : super(key: key);

  @override
  _DynamicWidgetState createState() => _DynamicWidgetState();
}

class _DynamicWidgetState extends State {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

创建Widget,重写createState()函数,然后实例State,在State中实现UI和具体的交互。

2.1 Stateful的生命周期:

widget生命周期.png

Widget的生命周期如上图所示,包含了 初始化状态改变销毁 三个阶段。

  • createState()

widget中重写createState()创建State实例.

  • initState()

界面创建之前调用的函数,完成一些需要在UI之前的操作,比如参数赋值之类。

  • didChangeDependencies()

initState()完成之后会调用改函数。

  • build()
    构建UI,返回一个widget,整个页面的创建在此完成。

  • deactivate()
    State被暂时从视图移除的时候会调用,页面push走、pop回来的时候都会调用。
    因为push、pop会改变widget在视图树位置,需要先移除再添加。
    必须要先调用super.deactivate()

  • dispose()
    页面被销毁的时候调用,如:pop操作。
    必须先调用父类super.dispose(),通常情况下,自己的释放逻辑放在super.dispose()之前,先操作子类在操作父类。

  • setState()
    每当我们手动调用这个函数是,会触发build()重新构建UI。

代码如下:

class _DynamicWidgetState extends State {
  @override
  void initState() {
    super.initState();
    print('------------initState');
  }

  @override
  Widget build(BuildContext context) {
    print('------build');
    return Container();
  }

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

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

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

调用的结果:


push_pop.png

红色为push进来的调用顺序,蓝色为pop走的调用顺序,beforePage是前一个界面的push走,和pop回来都调用了deactivate函数。


3.状态回调

在上述函数中基本上能完成相关逻辑开发,但是有时候并不能完全满足需求,比如:需要知道build()完成的时机,需要知道后台挂机和返回等。

  • addPostFrameCallback
    该回调会在widget渲染完成之后回调,只会调用一次,setState()刷新UI,也不会在调用。
    这里我们改造一下initState()
  @override
  void initState() {
    super.initState();
    print('------------initState');
    WidgetsBinding.instance.addPostFrameCallback(_buildAfter);
  }

  void _buildAfter(_) {
    print('------------_buildAfter');
  }

_buildAfter()函数会在build()调用之后紧接着调用,在这个函数里,我们可以做一些相关的逻辑,比如:查看其中wiget的sizeoffset等操作。


4.前后台监听

前后台的监听其实已经不是widget的生命周期了,应该属于App级别的生命周期,这里需要用到WidgetsBindingObserver

  • 修改State实例,mix WidgetsBindingObserver
class _DynamicWidgetState extends State with WidgetsBindingObserver {}
  • 在此修改initState()加入监听:
  @override
  void initState() {
    super.initState();
    print('------------initState');
    WidgetsBinding.instance.addPostFrameCallback(_buildAfter);
    WidgetsBinding.instance.addObserver(this);
  }
  • disposr()中移除监听,添加、移除监听和别的语言一样,需要一一对应,否则就会出现内存问题
  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
    print('------------dispose');
  }
  • 重写didChangeAppLifecycleState
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    print('------------$state--------');
  }

AppLifecycleState 具体的值有:

resumed
inactive
paused
suspending

按需在对应的状态写对应的逻辑就好了。

总结

自此widget的生命周期和App的生命周期都已经说完了,水平有限,哪里写错了,一定要告诉我哈~~

你可能感兴趣的:(Flutter(Widget和App)的生命周期)