Flutter中Stateless和Stateful的区别

Flutter中Stateless和Stateful的区别

实现Flutter app时,我们用widgets来构建app的UI。这些widgets有两种类型——statefule(有状态) 和 stateless(无状态)。本文中,笔者将深入探讨这两种类型的区别,从而帮大家更好地理解widget,掌握不同类型widget的使用时机。

Stateless widgets

当你创建的widge不需要管理任何形式的内部state时,你就应当使用StatelessWidgets。这类widget不需要任何可变的state,然后会在初始化数据后被使用。

例如,我们可以看一些我们熟知的Stateless widget:


这三个widget只是flutter部件集中的一小部分stateless widget。那么Stateless到底指的是什么呢?最简单直观的方法就是去读这些widget的源码(本文中没有源码分析,但是你可以点击这里看Text Widget的源码)。如果我们打开Text widget的源码,你会发现,这个部件没有状态可以被改变。通过构造方法把Text Widget初始化,然后用properties构建要被显示的内容,父widget实际上控制着这些这些窗口部件的显示状态。

在Text widget的例子中,父部件传入的属性,如文本,对齐方式,方向等会被其用作配置。前文我提到Stateless部件也是同样的用法。

但是当我们创建自己的widgets时,我们什么时候用stateless部件呢?考虑如下场景:

  • 你可能创建一个自定义的进度条控件,这个控件仅使用初始化的属性来展示进度给用户。这样就不需要持有任何状态,因为父部件会控制其是否显示,这样父部件就管理了这个widget本身是否显示的状态了。
  • 你可能创建一个用在列表中的单项widget,例如,一列蛋糕,每个蛋糕的widget都是由这个widget展示的。对于这个widget,你需要传入蛋糕的引用,从而能渲染这个widget的内容。这个widget同样不需要存储状态,它使用由父部件传入的数据,来控制对用户的显示。

从以上我们可以看出,Stateless widget是非动态的,它不依赖于除了传入的数据以外任何其他数据,这意味着改变其显示的唯一方式,就是通过改变传入其构造函数的参数。

Stateful widgets

另一方面,stateful widgets是动态的。他们允许我们创建一个能动随时间动态改变器内容的widget,并且不依赖于其初始化时被传入的静态状态。他们可以随着用户的输入,各种形式的异步回包或其他形式的状态变化而改变。

例如,我们可以看一些我们了解的stateful widget:

以上是flutter部件集中的一部分stateful widget。那么具体可变状态体现在哪里呢?(同样,你首先可以自己去看源码)以Image widget为例,我们可以发现这个文件有一点不同。首先,Image类继承自StatefulWidget类,然后和之前的Stateless widget一样,Image类的构造函数会接受要被这个类使用的属性参数。然而不同的是这里:

_ImageState createState() => new _ImageState();

这个被重写的方法被用来给我们的widget创建state。不用对Image类的工作方式了解的多明确,你可以发现这个文件的_ImageState持有对以下三个属性的引用:

ImageStream _imageStream; 
ImageInfo _imageInfo; 
bool _isListeningToStream = false;

ImageInfo属性用来给widget加载真实的图片。通过_handleImageChanged方法来调用State类的setState方法,表示:“hey,有些数据变啦,我们需要更新我们的State!”。

setState(() { 
    _imageInfo = imageInfo; 
});

此时,会用新的state重新构造widget,也就是说更新后imageInfo中的图片被加载。在这里,Image部件以动态方式运行 —— 监听图片引用的变化,一旦发生改变立马更新它的state。因而,它自己管理自己的state,而不是依赖于父类widget来做这个事情。值得去研究一下其他的Stateful widget是怎么运作的,它会帮你更好的理解什么时候该用stateful部件,什么时候该用stateless。一些简单的widget应该持有state的例子:

  • 比如我们构造一个控件来标识一个事物是否被用户标记。在这里,我们的可点击的view就应该持有一个对是否标记的引用 —— 这个状态应该随着每次点击做改变,同时这个类的构造方法也应该随着是否标记来设置不同的图标。
  • 比如我们有一个持有对当前选中项数目的widget,点击“+”会增加这个值。这里,我们的item就应该持有一个数目state,每次点击“+”,这个数目state都应该更新,并且这个数目在widget上的表现也应该在build方法里面更新。

希望这篇文章能帮你更好的理解stateless和stateful的区别。对这两者的正确使用,可以简化app结构,并让其可以更好地被复用或者调试。

原文:Stateful or Stateless widgets?

你可能感兴趣的:(安卓学习,Flutter)