Flutter框架,Widget、StatelessWidget

2021-07-09  本文已影响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;
    }());
  }

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

上一篇下一篇

猜你喜欢

热点阅读