Stateful or Stateless widgets?git
在建立一个Flutter App的时候,会遇到两种类型的控件github
在建立控件的时候,有一些控件不须要管理控件内部状态,这个时候就能够选择无状态控件。无状态控件除了用数据初始化之外的时刻,不须要改变它的状态。bash
在Flutter中,比较常见的有Text,Raised Button,Icon。less
以Text控件为例(源码),这个控件没有能够被改变的状态。异步
const Text.rich(
TextSpan(
text: 'Hello', // default text style
children: <TextSpan>[
TextSpan(text: ' beautiful ', style: TextStyle(fontStyle: FontStyle.italic)),
TextSpan(text: 'world', style: TextStyle(fontWeight: FontWeight.bold)),
],
),
)
复制代码
Text使用一个构造函数进行初始化,初始化时设置一些属性用于构建控件和控制显示内容。函数
父控件经过设置alignment、direction、text,来控制本身的显示,和管理子控件的显示。ui
那何时该选择使用stateless的控件呢?spa
例子一: 建立一个自定义的ProgressBar控件,使用的时候经过几个参数初始化就能展示给用户。这个控件不须要保留任何状态,它将被添加到父控件的控件树中,或者从父控件的控件树中移除,它的父控件经过管理本身的状态来控制ProgressBar的显示或隐藏。code
例子二: 建立一个内容列表中的列表子控件,好比一个蛋糕列表,蛋糕就是这个控件。这个控件将被填入蛋糕的信息,用于展现蛋糕。但这个控件不会保留状态,它只是使用填充的数据,经过父控件的设置来展现给用户。orm
从这些例子中能够看出,stateless的控件是非动态的。它只须要将数据传入其中,也就是说它只能经过构造函数传入的数据来控制如何显示。
Statefule widgets是Stateless widgets的对立面,它是动态的。它能够被随时的、动态的修改内容,不像Stateles widgets只能经过构造函数设置。改变的方式多是用户的输入,异步的响应或者对另外一个状态的变化作出反应。
在Flutter中,比较常见的有Image、Form、Checkbox等。
以Image为例(源码),Image控件的源文件看起来略有不一样,它是继承自StatefulWidget类,也能够经过构造函数传入数据来进行初始化,这些都和StatelessWidget相同。
不一样的地方是,这个控件中多了一个createState
方法(源码)
_ImageState createState() => new _ImageState();
复制代码
这个覆写的方法用来为控件建立状态。不用深刻Image如何运做的源码,就能够发现_ImageState是用来保存不一样的属性。
ImageStream _imageStream;
ImageInfo _imageInfo;
bool _isListeningToStream = false;
bool _invertColors;
复制代码
ImageInfo
用来为控件加载实际图片的属性。
_handleImageChanged
函数(源码)中使用了State类的setState函数,来表示状态发生了变动。
setState(() {
_imageInfo = imageInfo;
});
复制代码
当发生了状态变动时,控件将根据新状态从新构建,也就是说控件将加载更新后的imageInfo图片数据。这就是Image的动态行为的表现方式,它会一直监听图片引用,当引用放生变化时,它的状态也会改变。所以Image控件管理着它本身的状态,不依赖于父控件。
例子一: 建立一个控件用来显示一个记录是否被用户添加了书签。这个能够点击的控件将保留一个isBookmarked
的属性,当控件被点击的时候,它的状态将会被修改,在控件的build
函数中将会为记录设置上已经“已经添加过书签”的标志。
例子二: 建立一个控件用来保存当前被选中的记录数量,当点击“+”按钮的时候将会增长被选中的记录数量。这个控件将保存一个数量的状态,每次点击“+”按钮时,新的数量都会记录到State中,而且在build
函数中更新显示为新的数量。