美文网首页
Flutter(Widget和App)的生命周期

Flutter(Widget和App)的生命周期

作者: 陈贤森 | 来源:发表于2020-07-01 11:51 被阅读0次

    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<DynamicWidget> {
      @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<DynamicWidget> {
      @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<DynamicWidget> 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)的生命周期

          本文链接:https://www.haomeiwen.com/subject/kvxcqktx.html