Flutter之StatelessWidget和StateFulWidget区别

916 阅读3分钟

简介

Flutter作为跨平台的语言越来越被重视,特别是近两年许多互联网公司都在降本增效的时候,学会Flutter开发就变得十分重要了,有助于在日常工作中不被淘汰。

在Java中,万事万物皆为对象。同样在Flutter中,几乎所有的对象都是一个Widget。和其他开发语言不同的是,Flutter中的widget表示的含义更广泛,UI元素,View组件,主题,手势事件等都是一个Widget。

分类

Flutter中的Widget主要分为两类StatelessWidget和StatefulWidget。

  1. StatelessWidget表示无状态的Widget。
  2. StatefulWidget表示有状态的Widget。

区别

下面分别从代码结构,使用场景来区分两种Widget的不同.

代码结构

  1. StatelessWidget

从源码可以看出StatelessWidget是一个抽象类继承自Widget,内部默认实现创建了一个StatelessElement 对象和build方法。StatelessElement内部也只有一个update方法用来构建页面。

  1. StatefulWidget
abstract class StatefulWidget extends Widget {
  /// Initializes [key] for subclasses.
  const StatefulWidget({ super.key });
  @override
  StatefulElement createElement() => StatefulElement(this);

  /// [State] objects.
  @protected
  @factory
  State createState();
}

class StatefulElement extends ComponentElement {
 
.................
  @override
  Widget build() => state.build(this);
  State<StatefulWidget> get state => _state!;
  State<StatefulWidget>? _state;

 ...............

  @override
  void update(StatefulWidget newWidget) {
    super.update(newWidget);
    assert(widget == newWidget);
    final StatefulWidget oldWidget = state._widget!;
    state._widget = widget as StatefulWidget;
   ..............
      return true;
    }());
    rebuild(force: true);
  }

  @override
  void activate() {
    super.activate();
    state.activate();
    assert(_lifecycleState == _ElementLifecycle.active); // otherwise markNeedsBuild is a no-op
    markNeedsBuild();
  }

  @override
  void deactivate() {
    state.deactivate();
    super.deactivate();
  }

  @override
  void unmount() {
    super.unmount();
    state.dispose();
    state._element = null;

    _state = null;
  }

  @override
  InheritedWidget dependOnInheritedElement(Element ancestor, { Object? aspect }) {
    assert(ancestor != null);
      .....
    return super.dependOnInheritedElement(ancestor as InheritedElement, aspect: aspect);
  }

  bool _didChangeDependencies = false;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _didChangeDependencies = true;
  }

  @override
  DiagnosticsNode toDiagnosticsNode({ String? name, DiagnosticsTreeStyle? style }) {
    return _ElementDiagnosticableTreeNode(
      name: name,
      value: this,
      style: style,
      stateful: true,
    );
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<State<StatefulWidget>>('state', _state, defaultValue: null));
  }
}

StatefulWidget内部StatefulElement 中不仅有update()方法还有activate,deactivate,didChangeDependencies等方法。具体方法使用以后慢慢讲解。

使用场景

1 StatelessWidget

StatelessWidget从字面意思就可以看出是无状态的Widget。这里的无状态通俗来说,一旦控件确定,就不能改变其状态。包括显示状态,点击状态等。通常用来表示一些不涉及到页面变化,更新等控件。

示例:

这里封装了一个CommonButton按钮,按钮的构造函数中只传入了text文本和点击事件的回调。也就是说一旦传入了text,按钮本身的显示状态并不会发生改变,而且点击事件也是由调用者来实现,对应按钮本身来说不会发生任何改变。

2 StatefulWidget

StatefulWidget表示有状态的widget,或者是说有生命周期的Widget,这里的状态同样是指widget本身的状态,如形状,角度,颜色,背景色等发生改变。

示例:

同样还是CommonButton,这次继承自StatefulWidget,给按钮添加了一个旋转动画,在initState方法中初始化动画控制器,在dispose方法中解绑控制器,由于是给按钮本身添加了动画,当点击按钮时,按钮自身状态发生了改变。所以必须要用StatefulWidget,如果用StatelessWidget是无法实现按钮自身的旋转的。读者可以动手试试。

总结

在Flutter中,不论是StatelessWidget还是StatefulWidget都是经常使用的控件,熟练掌握Widget的基本使用场景有效提高开发效率,特别是正确区分不同Widget的使用场景,本文从简单的Widget开始介绍StatelessWidget和StatefulWidget和区别和使用场景。

后续会使用Flutter语言仿一个抖音的项目。感兴趣的同学可以点击关注哦!