flutter中如果使用widget, 那么无可避免的就要接触到StatelessWidget和StatefulWidget这两样东西, 这两样东西表示什么呢?
首先我们需要明白flutter中的编程范式, flutter的视图开发是声明式的, 它的核心设计思想是将视图和数据进行分离,
如果说widget表示的是视图组件的话, 那么state就是视图组件的数据, 如果一个组件是stateless, 那就表示这个widget是静态的, 也就是你所要构建用户界面不随状态信息的变化而变化。 如果一个组件是stateful, 那就表示它会随着状态信息而改变。
statelessWidget
statelesswidget在flutter中的大体形式是这样的:
class --- extends StatelessWidget {
Widget build(BuildContext context) {
return ----
}
}
下面是Text这个widget的部分源码:
class Text extends StatelessWidget {
//构造函数
const Text(this.data, {
Key key,
this.textAligin,
this.textDirction,
}) : assert(data != null),
textSpan = null,
super(key: key);
//一些属性
final String data;
final textAlign textAligin;
final textDirction textDirction;
@override
Widget build(BuildContext contxet) {
...
Widget result = RichText(
);
return result;
}
}
可以看到, 在构造方法将其属性列表赋值后, build方法随即讲子组件RichText通过其属性列表(如文本data, 对齐方式textAlign, 文本展示方向textDirction)初始化后返回, 之后Text内部不再响应外部数据的变化。
简单的判断规则: 父widget是否能通过初始化参数完全控制其UI展示效果?, 如果能我们就可以使用statelessWidget来设计构造函数接口了。
第一个例子就是, 我需要创建一个自定义的弹窗控件
statefulwidget
statefulwidget的常见形式是这样的:
class --- extends StatefulWidget {
--- createState() => ----();
}
class --- extends State<---> with xxx {
Widget build(BuildContext context)
}
下面以Image这个组件源码来看看:
class Image extends StatefulWidget {
const Image({
Key? key,
@required this.image,
//其它参数
}) : assert(image != null),
super(key: key);
final ImageProvider image;
//其它属性
@override
_ImageState createState() => _ImageState();
}
class _ImageState extends State<Image> {
ImageInfo _ImageInfo;
//其它属性
...
void _handleImageChanged(ImageInfo imageInfo, bool synchronousCall) {
setState((){
_imageInfo = imageInfo;
});
}
@override
Widget build(BuildContext context) {
final RawImage image = RawImage(
image: _imageInfo?.image,
//其它的初始化配置
);
return image;
}
...
}
Image类的构造函数会接收要被这个类使用的属性参数, 然而不同的是, image类并没有build方法来创建视图, 而是通过
createState方法创建了一个类型为_ImageState的state对象, 然后由这个对象负责视图的构建
这个state对象持有并处理了Image类中的状态变化。所以我就以_imageInfo属性为例子来展开说明。
_imageInfo属性用来给Widget加载真实的图片, 一旦State对象通过_handleImageChange方法监听到_imageInfo属性发生了变化, 就会立即调用_imageState类的setState()方法通知Flutter框架: 数据发生变化, 请使用更新后_imageInfo
数据重新加载图片, 而Flutter框架则会标记视图状态, 更新UI。
慎用statefulWidget
widget是不可变的, 更新就意味着销毁加重建(build), statelessWidget是静态的, 一旦创建则无需更新, 而对于statefulWidget来说, 在State类中调用setState方法更新数据, 会触发视图的销毁和重建, 也将间接地触发其每个子
Widget的销毁和重建, 这样就会损失效率。