美文网首页
Flutter框架,Widget、StatelessWidget

Flutter框架,Widget、StatelessWidget

作者: 程就人生 | 来源:发表于2021-07-09 21:48 被阅读0次

    最近几天有一搭没一搭的学习 Flutter,在 Flutter 中一切皆 Widget ,那么组件是不是单单指UI元素呢?比如文本框、按钮、弹窗等等一系列 UI 控件,想必很多新入手 Flutter 的朋友都会心存疑惑。答案是否定的。

    在 Flutter中,控件是Element,Widget 更多的指的是UI元素的一个配置数据,并且一个Widget可以对应多个UI元素,比如手势检测的 GestureDetector widget。编码中最多使用的抽象类就是无状态组件 StatelessWidget 和 有状态组件StatefulWidget ,而这两个类都继承Widget,接下来看看这三个类的源码吧。

    widget组件源码分析

    //该类是一个抽象类,继承DiagnosticableTree(诊断树,主要作用是提供调试信息)
    @immutable
    abstract class Widget extends DiagnosticableTree {
    
      // 在之类中初始化key
      const Widget({ this.key });
    
      // 组件唯一标识,判断时使用,决定是否在下一次build时复用旧的widget,决定条件在canUpdate()方法中
      final Key? key;
    
      // 创建一个Element对象,子类需重写该方法
      @protected
      @factory
      Element createElement();
    
      //查看组件的运行类型及唯一标识
      @override
      String toStringShort() {
        final String type = objectRuntimeType(this, 'Widget');
        return key == null ? type : '$type-$key';
      }
    
      //重写父类的方法,主要设置诊断树的一些特性
      @override
      void debugFillProperties(DiagnosticPropertiesBuilder properties) {
        super.debugFillProperties(properties);
        properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
      }
    
      //重写父类的方法
      @override
      @nonVirtual
      bool operator ==(Object other) => super == other;
    
      //重写父类的方法,获取父类的hashCode
      @override
      @nonVirtual
      int get hashCode => super.hashCode;
    
      // 组件是否被更改的判断
      static bool canUpdate(Widget oldWidget, Widget newWidget) {
        return oldWidget.runtimeType == newWidget.runtimeType
            && oldWidget.key == newWidget.key;
      }
    
      // 获取组件类型,是无状态的组件,还是有状态的组件,还是其他
      static int _debugConcreteSubtype(Widget widget) {
        return widget is StatefulWidget ? 1 :
        widget is StatelessWidget ? 2 :
        0;
      }
    }
    

    Widget 又分为无状态的 StatelessWidget 和有状态的StatefullWidget 两大类,这两个类都继承了Widget。
    StatelessWidget 源码分析

    /// StatelessWidget是一个抽象类,继承Widget,用于不需要维护状态的场景
    abstract class StatelessWidget extends Widget {
      /// 帮助子类初始化key
      const StatelessWidget({ Key? key }) : super(key: key);
    
      /// 创建一个无状态的组件,并在本地管理这个组件,无需子类重写
      /// StatelessElement 与 StatelessWidget 相对应
      @override
      StatelessElement createElement() => StatelessElement(this);
    
      /// 子类需要重写的方法,构建无状态组件
      @protected
      Widget build(BuildContext context);
    }
    

    StatefulWidget 源码分析

    /// StatelessWidget是一个抽象类,继承Widget,用于需要维护状态的场景
    abstract class StatefulWidget extends Widget {
      /// 帮助子类初始化key
      const StatefulWidget({ Key? key }) : super(key: key);
    
      /// 创建一个有状态的组件,并在本地管理这个组件,无需子类重写
      /// StatefulElement 与 StatefulWidget相对应
      @override
      StatefulElement createElement() => StatefulElement(this);
    
      /// 状态管理,需要子类重写
      @protected
      @factory
      State createState();
    }
    

    那么,State又是个啥玩意呢?一个StatefulWidget类会对应一个State类,State表示与其对应的StatefulWidget要维护的状态。

    State源码分析

    /// State也是一个抽象类,与StatefulWidget类一一对应
    @optionalTypeArgs
    abstract class State<T extends StatefulWidget> with Diagnosticable {
      
      T get widget => _widget!;
      T? _widget;
    
      /// _StateLifecycle生命周期包括:created[State.initState]、initialized[State.didChangeDependencies]、ready、defunct[State.dispose] 
      _StateLifecycle _debugLifecycleState = _StateLifecycle.created;
    
      bool _debugTypesAreRight(Widget widget) => widget is T;
    
      // 上下文获取,通过context可以从上下文获取其他组件,context.findAncestorWidgetOfExactType<Scaffold>()
      BuildContext get context {
        assert(() {
          if (_element == null) {
            /// 省略部分
          }
          return true;
        }());
        return _element!;
      }
      StatefulElement? _element;
    
      bool get mounted => _element != null;
    
      // 初始化状态,组件的生命周期开始,如果子类重写该方法必须调用父类即:super.initState();
      @protected
      @mustCallSuper
      void initState() {
        assert(_debugLifecycleState == _StateLifecycle.created);
      }
    
      /// 变更组件状态
      @mustCallSuper
      @protected
      void didUpdateWidget(covariant T oldWidget) { }
    
      /// 重写组装组件
      @protected
      @mustCallSuper
      void reassemble() { }
    
      /// 设置组件状态,将需要保持的状态放置到该方法中
      @protected
      void setState(VoidCallback fn) {
        assert(fn != null);
        assert(() {
          if (_debugLifecycleState == _StateLifecycle.defunct) {
            /// 省略部分
          }
          if (_debugLifecycleState == _StateLifecycle.created && !mounted) {
            /// 省略部分
          }
          return true;
        }());
        final Object? result = fn() as dynamic;
        assert(() {
          if (result is Future) {
            /// 省略部分
          }
          return true;
        }());
        _element!.markNeedsBuild();
      }
    
      // 使状态无效
      @protected
      @mustCallSuper
      void deactivate() { }
    
      // 销毁组件
      @protected
      @mustCallSuper
      void dispose() {
        assert(_debugLifecycleState == _StateLifecycle.ready);
        assert(() {
          _debugLifecycleState = _StateLifecycle.defunct;
          return true;
        }());
      }
    

    如果没有实际的编码经验,看源码,只能对组件的状态管理有个粗略的理解,到底怎么使用,还需要练起来感觉一下的。

    相关文章

      网友评论

          本文标题:Flutter框架,Widget、StatelessWidget

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