美文网首页
Flutter开发1:Widget与生命周期

Flutter开发1:Widget与生命周期

作者: 十二栗子 | 来源:发表于2022-05-03 18:09 被阅读0次

    什么是Widget

    Flutter中几乎所有的对象都是一个Widget,这与原生开发中“控件”概念稍有不同,Flutter中的Widget表示一切与UI框架相关的对象,例如:手势检测 GestureDetector,而原生开发中的Widget控件通常仅仅指UI布局中的各种控件,不包含Flutter中的功能型Widget。

    标识符:Key

    Flutter 是响应式框架,每次刷新 UI 的时候,都会重新构建新的 Widget树,并和之前的 Widget树进行对比,计算出变化的部分,这个计算过程就是diff,在 diff 过程中,如果能提前知道哪些 Widget 没有变化,就能提高 diff 的性能,这时候就需要使用到标识符。

    给 Widget 添加一个唯一的标识符,然后在 Widget树 的 diff 过程中查看刷新前后的 Widget树,如果标识符相同,则说明 Widget 没有变化,否则说明 Widget 有变化。

    这个标识符就是Flutter 中的Key属性,所有 Widget 都有 Key 属性

    Key有两种类型:

    • Local Key(局部Key)
    • Global Key(全局Key)

    什么是StatelessWidget

    它是一个比较简并继承自Widget类的一个类,常在build方法中通过嵌套其它Widget来构建UI。当我们需要组合并封装多个Widget控件,且不需要维护数据状态时,可以自定义Widget并继承该类。它最大的特点是仅表示当前一帧的页面,当页面动态变化时,每次都会重建数据。

    需要注意,它的内部成员变量是immutable的,通常需要使用final修饰。

    什么是 StatefulWidget

    它也是继承自Widget类,不同的是一个StatefulWidget类就会对应一个State类。State表示与其对应的StatefulWidget要维护的状态,且State中存在与原生开发中类似的生命周期回调。

    State 类有两个功能:

    • build() 方法创建 UI
    • setState() 方法刷新 UI

    调用setState()方法并在其中修改数据的值,会触发 State 的 build() 方法,重建 Widget,重建时会重新绑定数据,这时数据已变化,从而达到更新页面的目的。

    State 中还有三个重要的成员变量

    • widget 通过该变量可访问 StatefulWidget 中定义的成员属性
    • context 用于获取当前 StatefulWidget 中的上下文
    • mounted 判断当前 State 是否已加载到树中。在State 对象创建之后,initState() 调用之前,框架会将 State 对象加载到树中,此时 mounted 会变为 true,当 State dispose 之后,mounted 就为 false。因此,在setState() 调用前可判断 mounted 的值以避免异常,mounted 为 false 时调用setState()会报错。
    if(mounted){
        setState((){
            // :TODO
        })
    }
    

    StatelessWidget 和 StatefulWidget的区别

    • StatelessWidget 是 UI 不可变化的 Widget,创建完后 UI 就不能发生变化;
    • StatefulWidget 是 UI 可变化的 Widget,并存在生命周期,创建完后 UI 可以更改。通常的,一个单独页面的根Widget应当使用StatefulWidget 包裹,存在并需要封装动画时,也需要使用StatefulWidget封装控件。

    widget生命周期回调

    StatefulWidget 生命周期回调

    • initState 当Widget 第一次插入到 Widget树时被调用,对于每一个State对象,该回调只会调用一次,所以通常会在回调中做一些初始化。覆写此方法时,应在调用super.iniState()之后
    • didChangeDependencies 创建时在initState 之后被调用,或者当State对象的依赖发生变化时调用,子类很少覆写
    • build 构建该Widget 表示的UI元素。此方法在不同情况下被调用:
      1.调用initState之后
      2.调用didUpdateWidget之后
      3.调用setState之后
      4.当State对象的依赖更改(didChangeDependencies)之后
      5.当State对象从树中一个位置移除后(调用deactivate)又重新插入到树的其它位置时调用
    • didUpdateWidget 当Widget 的状态发生改变时调用,例如调用setState
    • deactivate 当State对象从树中被移除时,会调用此回调。如果移除后没有重新插入到树中则紧接着会调用dispose方法,如果覆写此方法,应在调用super.deactivate()之前
      dispose 当State对象从树中被永久移除时调用。通常在此回调中释放资源,如果覆写此方法,应在调用super.dispose()之前
    class _MyHomePageState extends State<MyHomePage> {
    //定义变量区域
      final GlobalKey _gk = GlobalKey();
      int count = 0;
    
    //定义其他函数,放前面或者后面都可以
      void _showHint() {
    
      }
    
    //widget生命周期函数如下
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        debugPrint('initState');
      }
    
      @override
      void didChangeDependencies() {
        super.didChangeDependencies();
        debugPrint('didChangeDependencies');
      }
    
      @override
      Widget build(BuildContext ctx) {
        // this.context;
        return Scaffold();
      }
    
      @override
      void didUpdateWidget(covariant MyHomePage oldWidget) {
        super.didUpdateWidget(oldWidget);
        debugPrint('didUpdateWidget');
      }
    
      @override
      void deactivate() {
        super.deactivate();
        debugPrint('deactivate');
      }
    
      @override
      void dispose() {
        super.dispose();
        debugPrint('dispose');
      }
    }
    
    

    App 的生命周期

    除了Widget,App本身也存在生命周期,这类似原生App的生命周期,主要指进入app,按home键等系统级的操作。

    要监听系统级的App生命周期回调,需要在页面的State类上混入WidgetsBindingObserver类,并实现didChangeAppLifecycleState回调方法
    注意:不要忘了注册和移除监听器,否则不生效

    class _MyAppState extends State<MyApp> with WidgetsBindingObserver{
    
      @override
      void initState() {
        super.initState();
        /// 注册监听器
        WidgetsBinding.instance.addObserver(this);
      }
    
      @override
      void didChangeAppLifecycleState(AppLifecycleState state) {
        switch (state) {
          case AppLifecycleState.resumed:
            break;
          case AppLifecycleState.inactive: 
            break;
          case AppLifecycleState.paused: 
            break;
          case AppLifecycleState.detached: 
            break;
        }
      }
    
      @override
      void dispose() {
        /// 移除监听器
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }
    }
    

    AppLifecycleState提供四种状态

    • resumed 应用处于前台,可见可交互
    • inactive应用处于非活动状态。在 iOS 上,当在通话、响应TouchID请求、进入应用切换器或控制中心时,应用会过渡到这个状态。在Android上,当其他活动被聚焦时,例如分屏应用、电话呼叫、画中画应用、弹出系统对话框时,应用会过渡到这个状态
    • paused应用不可见,处于后台运行时处于该状态
    • detached Flutter引擎第一次初始化时正在加载视图,或在视图因Navigator.pop 而被摧毁后时,处于该状态

    相关文章

      网友评论

          本文标题:Flutter开发1:Widget与生命周期

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