生命周期

2022/11/19 Flutter生命周期

本文介绍Flutter的状态组件生命周期,并详细介绍各个阶段函数的执行时机和应用场景。

# 组件生命周期

  • StatefulWidget 生命周期

    • StatefulWidget 生命周期

    • 执行顺序,从上往下

      名称 说明
      createState 创建 State 只执行 1 次
      initState 初始 State, mounted 等于 true, 只执行 1 次
      didChangeDependencies 父或祖先 widget 中的 InheritedWidget 改变时会被调用
      build UI 被重新渲染的时候多次执行
      addPostFrameCallback 渲染结束回调,只执行 1 次
      didUpdateWidget 父类 setState 后,子类就会触发
      deactivate 从组件树中移除 State 时调用
      dispose 组件被释放时调用
    • initState初始状态数据。

      // 初始 State, mounted 等于 true, 只执行 1 次
      
      void initState() {
        // TODO: implement initState
        super.initState();
        print('initState');
      }
      
      1
      2
      3
      4
      5
      6
      7
    • build 渲染视图,可多次。

      
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(title: const Text('无状态')),
            body: Column(
              children: [
                ElevatedButton(
                  onPressed: () {
                    if (mounted == true) {
                      setState(() {
                        imgUrl = imgUrl == img1 ? img2 : img1;
                      });
                    }
                  },
                  child: const Text("切换图片"),
                ),
                Text(imgUrl)
              ],
            ),
          ),
        );
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
    • mounted 状态。

    flutter 分配完你的组件树位置,会设置 mounted 为 true,需要在 mounted == true 情况下,调用 setState() 来更新 UI ,这才是安全的操作。。

    ElevatedButton(
      onPressed: () {
        if (mounted == true) {
          setState(() {
            imgUrl = imgUrl == img1 ? img2 : img1;
          });
        }
      },
      child: const Text("切换图片"),
    )
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    • didChangeDependencies父或祖先 widget 中的 InheritedWidget 改变时会被调用。

      // 父或祖先 widget 中的 InheritedWidget 改变时会被调用
      
      void didChangeDependencies() {
        // TODO: implement didChangeDependencies
        super.didChangeDependencies();
        print('didChangeDependencies');
      }
      
      1
      2
      3
      4
      5
      6
      7
    • didUpdateWidget父类 setState 后,子类就会触发。

      
      void didUpdateWidget(covariant BannerWidget oldWidget) {
        // TODO: implement didUpdateWidget
        super.didUpdateWidget(oldWidget);
        print('didUpdateWidget');
      }
      
      1
      2
      3
      4
      5
      6
    • addPostFrameCallback渲染结束回调,只执行 1 次。

      // 初始 State, mounted 等于 true, 只执行 1 次
      
      void initState() {
        // TODO: implement initState
        super.initState();
        imgUrl = img1;
        print('initState');
      
        // 渲染结束回调,只执行 1 次
        SchedulerBinding.instance?.addPostFrameCallback((timeStamp) {
          print('SchedulerBinding');
          print(timeStamp);
        });
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
    • deactivate从组件树中移除 State 时调用。

      
      void deactivate() {
        super.deactivate();
        print("deactivate");
      }
      
      1
      2
      3
      4
      5
    • dispose组件被释放时调用。

      
      void dispose() {
        print("dispose");
        super.dispose();
      }
      
      1
      2
      3
      4
      5
    • 完整代码

      import 'package:flutter/material.dart';
      import 'package:flutter/scheduler.dart';
      
      void main(List<String> args) {
        runApp(const BannerWidget());
      }
      
      // 无状态组件
      const img1 =
          "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg-blog.csdnimg.cn%2Fimg_convert%2Fa092a42776106d7e76e867d590b971f0.png&refer=http%3A%2F%2Fimg-blog.csdnimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1671269160&t=c20102eb0a87d3fd49f9a4b3776daedd";
      const img2 =
          "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.zhimg.com%2Fv2-3b345224fce3c12bf0a822aa488ae2fc_1440w.jpg%3Fsource%3D172ae18b&refer=http%3A%2F%2Fpic1.zhimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1671270631&t=53cd2791f93fd3038012614d1c5e99ce";
      
      // 有状态组件就像一个舞台,舞台上都是无状态组件
      class BannerWidget extends StatefulWidget {
        const BannerWidget({Key? key}) : super(key: key);
      
        
        State<BannerWidget> createState() => _BannerWidgetState();
      }
      
      class _BannerWidgetState extends State<BannerWidget> {
        String imgUrl = '';
      
        // 初始 State, mounted 等于 true, 只执行 1 次
        
        void initState() {
          // TODO: implement initState
          super.initState();
          imgUrl = img1;
          print('initState');
      
          // 渲染结束回调,只执行 1 次
          SchedulerBinding.instance?.addPostFrameCallback((timeStamp) {
            print('SchedulerBinding');
            print(timeStamp);
          });
        }
      
        // 父或祖先 widget 中的 InheritedWidget 改变时会被调用
        
        void didChangeDependencies() {
          // TODO: implement didChangeDependencies
          super.didChangeDependencies();
          print('didChangeDependencies');
        }
      
        
        void didUpdateWidget(covariant BannerWidget oldWidget) {
          // TODO: implement didUpdateWidget
          super.didUpdateWidget(oldWidget);
          print('didUpdateWidget');
        }
      
        
        Widget build(BuildContext context) {
          return MaterialApp(
            home: Scaffold(
              appBar: AppBar(title: const Text('无状态')),
              body: Column(
                children: [
                  ElevatedButton(
                    onPressed: () {
                      if (mounted == true) {
                        setState(() {
                          imgUrl = imgUrl == img1 ? img2 : img1;
                        });
                      }
                    },
                    child: const Text("切换图片"),
                  ),
                  Text(imgUrl)
                ],
              ),
            ),
          );
        }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
  • StatelessWidget 生命周期

无状态组件,不需要处理生命周期,直接显示即可,在源码中可见 createElement() 创建组件到组件树,不需要重写去维护。

# APP生命周期

  • APP生命周期以混入方式 WidgetsBindingObserver

    class _BannerWidgetState extends State<BannerWidget> with WidgetsBindingObserver {
    
    }
    
    1
    2
    3
  • 需要在initState中添加观察者

    
    void initState() {
      // TODO: implement initState
      super.initState();
    
      // 注入观察者
      WidgetsBinding.instance?.addObserver(this);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
  • 生命周期发生回调时didChangeAppLifecycleState

    // 生命周期变化时回调
    
    void didChangeAppLifecycleState(AppLifecycleState state) {
      // TODO: implement didChangeAppLifecycleState
      super.didChangeAppLifecycleState(state);
      print(didChangeAppLifecycleState);
    }
    
    1
    2
    3
    4
    5
    6
    7
  • 销毁观察者removeObserver

    
    void dispose() {
      super.dispose();
      WidgetsBinding.instance?.removeObserver(this); //销毁观察者
    }
    
    1
    2
    3
    4
    5
  • 名称 说明
    resumed 应用程序可见且响应用户输入。
    inactive 应用程序处于非激活状态,无法响应用户输入。
    pause 应用程序不可见且无法响应用户输入,运行在后台。
    detached 应用程序仍寄存在 Flutter 引擎上,但与平台 View 分离。
    suspending 应用被挂起,此状态 IOS 永远不会回调
  • didChangeAccessibilityFeatures当前系统改变了一些访问性活动的回调

    
    void didChangeAccessibilityFeatures() {
      super.didChangeAccessibilityFeatures();
      print("didChangeAccessibilityFeatures");
    }
    
    1
    2
    3
    4
    5
  • didHaveMemoryPressure低内存回调

    
    void didHaveMemoryPressure() {
      super.didHaveMemoryPressure();
      print("didHaveMemoryPressure");
    }
    
    1
    2
    3
    4
    5
  • didChangeLocales用户本地设置变化时调用,如系统语言改变

    
    void didChangeLocales(List<Locale>? locale) {
      super.didChangeLocales(locale);
      print("didChangeLocales");
    }
    
    1
    2
    3
    4
    5
  • didChangeMetrics应用尺寸改变时回调,例如旋转

    
    void didChangeMetrics() {
      super.didChangeMetrics();
      Size? size = WidgetsBinding.instance?.window.physicalSize;
      print("didChangeMetrics  :宽:${size?.width} 高:${size?.height}");
    }
    
    1
    2
    3
    4
    5
    6
  • didChangePlatformBrightness系统切换主题时回调

    
    void didChangePlatformBrightness() {
      super.didChangePlatformBrightness();
      print("didChangePlatformBrightness");
    }
    
    1
    2
    3
    4
    5
  • didChangeTextScaleFactor文字系数变化

    
    void didChangeTextScaleFactor() {
      super.didChangeTextScaleFactor();
      print(
          "didChangeTextScaleFactor  :${WidgetsBinding.instance?.window.textScaleFactor}");
    }
    
    1
    2
    3
    4
    5
    6
最后更新时间: 2022/11/29 07:33:47