Flutter 的视图开发是声明式的,其核心设计思想就是将视图和数据分离,除了设计好 Widget 布局方案之外,还需要提前维护一套文案数据集,并为需要变化的 Widget 绑定数据集中的数据,使 Widget 根据这个数据集完成渲染。
当需要变更界面时,我们只要改变数据集中的文案数据,并通知 Flutter 框架触发 Widget 的重新渲染即可。这样一来,开发者将无需再精确关注 UI 编程中的各个过程细节,只要维护好数据集即可。比起命令式的视图开发方式需要挨个设置不同组件(Widget)的视觉属性,这种方式要便捷得多。
在 Widget 的生命周期内,应用到 State 中的任何更改都将强制 Widget 重新构建。其中,对于组件完成创建后就无需变更的场景,状态的绑定是可选项。这里“可选”就区分出了 Widget 的两种类型,即:StatelessWidget 不带绑定状态,而 StatefulWidget 带绑定状态。当你所要构建的用户界面不随任何状态信息的变化而变化时,需要选择使用 StatelessWidget,反之则选用 StatefulWidget。前者一般用于静态内容的展示,而后者则用于存在交互反馈的内容呈现中。
在 Flutter 中,Widget 采用由父到子、自顶向下的方式进行构建,父 Widget 控制着子 Widget 的显示样式,其样式配置由父 Widget 在构建时提供。用这种方式构建出的 Widget,有些(比如 Text、Container、Row、Column 等)在创建时,除了这些配置参数之外不依赖于任何其他信息,换句话说,它们一旦创建成功就不再关心、也不响应任何数据变化进行重绘。在 Flutter 中,这样的 Widget 被称为 StatelessWidget(无状态组件)。
class Text extends StatelessWidget {
// 构造方法及属性声明部分
final String data;
final TextAlign textAlign;
final TextDirection textDirection;
const Text({
Key ?key,
this.data ="test",
this.textAlign =TextAlign.center,
this.textDirection =TextDirection.ltr,
}) :super(key: key);
@override
Widget build(BuildContext context) {
Widget result = RichText(
// 初始化配置
)
);
return result;
}
}
可以看到,在构造方法将其属性列表赋值后,build 方法随即将子组件 RichText 通过其属性列表(如文本 data、对齐方式 textAlign、文本展示方向 textDirection 等)初始化后返回,之后 Text 内部不再响应外部数据的变化。父 Widget 能通过初始化参数完全控制其 UI 展示效果,就可以使用 StatelessWidget 来设计构造函数接口了。
与 StatelessWidget 相对应的,有一些 Widget(比如 Image、Checkbox)的展示,除了父 Widget 初始化时传入的静态配置之外,还需要处理用户的交互(比如,用户点击按钮)或其内部数据的变化(比如,网络数据回包),并体现在 UI 上。这些 Widget 创建完成后,还需要关心和响应数据变化来进行重绘。在 Flutter 中,这一类 Widget 被称为 StatefulWidget(有状态组件)。
StatefulWidget 是以 State 类代理 Widget 构建的设计方式实现的。
class Image extends StatefulWidget {
// 构造方法及属性声明部分
const Image({
Key ?key,
required this.image,
// 其他参数
}) :super(key: key);
final ImageProvider image;
// 其他属性
@override
_ImageState createState() =>_ImageState();
}
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 以一种动态的方式运行:监听变化,更新视图。与 StatelessWidget 通过父 Widget 完全控制 UI 展示不同,StatefulWidget 的父 Widget 仅定义了它的初始化状态,而其自身视图运行的状态则需要自己处理,并根据处理情况即时更新 UI 展示。
需要注意的是,除了我们主动地通过 State 刷新 UI 之外,在一些特殊场景下,Widget 的 build 方法有可能会执行多次。因此,我们不应该在这个方法内部,放置太多有耗时的操作。正确评估你的视图展示需求,避免无谓的 StatefulWidget 使用,是提高 Flutter 应用渲染性能最简单也是最直接的手段。
网友评论