Flutter中的Build方法为什么会在State中,而不在StatefulWidget中?

news/2024/7/8 15:05:54 标签: Flutter, build, StatefulWidget

官网中build方法的文档地址:
https://api.flutter.dev/flutter/widgets/State/build.html

在学习写StatefulWidget的时候,就有这个疑问了,为什么要把build方法写在State中?
为什么不是跟写StatelessWidget一样,直接把build方法写在StatelessWidget中呢?

网上也有人有这样的疑问:链接找不到了。。。

于是看到了官网上的相关说明:

Design discussion
Why is the build method on State, and not StatefulWidget?

以下是对原文的Google直译,看不太懂的话可以直接参考对照原文一起看


例如,AnimatedWidget是StatefulWidget的子类,它为其子类引入了一个抽象的Widget构建(BuildContext context)方法来实现。如果StatefulWidget已经有一个带有State参数的构建方法,AnimatedWidget将被强制将其State对象提供给子类,即使它的State对象是AnimatedWidget的内部实现细节。

从概念上讲,StatelessWidget也可以以类似的方式实现为StatefulWidget的子类。如果构建方法是在StatefulWidget而不是State上,那就不可能了。

将构建函数放在State而不是StatefulWidget上也有助于避免与隐式捕获它的闭包相关的一类错误。如果您在StatefulWidget上的构建函数中定义了一个闭包,那么该闭包将隐式捕获thisthis就是当前的Widget实例,并且在该范围内将具有该实例的(不可变)字段:

class MyButton extends StatefulWidget {
  ...
  final Color color;

  @override
  Widget build(BuildContext context, MyButtonState state) {
    ... () { print("color: $color"); } ...
  }
}

例如,假设父级构建MyButton,颜色为蓝色,print函数中的$ color指的是蓝色,如预期的那样。 现在,假设父级使用绿色重建MyButton。 由第一个build创建的闭包仍隐式引用原始的那个Widget,即使Widget已更新为绿色,$ color仍会打印蓝色。

相反,使用State对象上的构建函数,在构建期间创建的闭包隐式捕获State实例而不是widget实例:

class MyButtonState extends State<MyButton> {
  ...
  @override
  Widget build(BuildContext context) {
    ... () { print("color: ${widget.color}"); } ...
  }
}

现在,当父级使用绿色重建MyButton时,第一个构建创建的闭包仍然引用State对象,该对象在重建时保留,但框架已更新该State对象的widget属性以引用新的MyButton实例和$ {widget. color}按预期打印绿色。
上面那段话,可以参考State的源码中属性T _widget的文档注释:

abstract class State<T extends StatefulWidget> extends Diagnosticable {
  /// The current configuration.
  ///
  /// A [State] object's configuration is the corresponding [StatefulWidget]
  /// instance. This property is initialized by the framework before calling
  /// [initState]. If the parent updates this location in the tree to a new
  /// widget with the same [runtimeType] and [Widget.key] as the current
  /// configuration, the framework will update this property to refer to the new
  /// widget and then call [didUpdateWidget], passing the old configuration as
  /// an argument.
  T get widget => _widget;
  T _widget;

也可以看看:

https://stackoverflow.com/questions/46107609/statelesswidgets-vs-statefulwidget

Flutter Widget简介,文中有一部分也介绍了该问题,是用的官网解释的翻译版本。

StatefulWidget,其中包含有关性能注意事项的讨论。
其中有一个视频 How Stateful Widgets Are Used Best


http://www.niftyadmin.cn/n/1541165.html

相关文章

spark2.2.1安装、pycharm连接spark配置

一、单机版本Spark安装 Win10下安装Spark2.2.1 1. 工具准备 JDK 8u161 with NetBeans 8.2&#xff1a; http://www.oracle.com/technetwork/java/javase/downloads/jdk-netbeans-jsp-142931.html spark: spark-2.2.1-bin-hadoop2.7&#xff1a; https://spark.apache.org/downl…

快速开发平台程序运行环境

系统运行环境 服务端 硬件环境 内存:1GB以上CPU:2.0GHz以上硬盘:40G以上软件环境 操作系统&#xff1a;Windos Xp以上数据库&#xff1a;SQL Server 2005 Sp2以上.Net环境:Microsoft .NET Framework 2.0 Sp2以上客户端 硬件环境 内存:256M以上CPU:1.5GHz以上硬盘:40G以上软件环…

Flutter学习资料汇总

首先Flutter为何要选用Dart&#xff1a; Flutter为何会选用Dart&#xff1f; 主要资源&#xff1a; Flutter官网Flutter中文网优达学城上的视频Medium官网上的Flutter板块Youtube上的Flutter视频Flutter的一些第三方库&#xff0c;各种插件Flutter的官方文档Flutter中文官方…

Avatar mirrors users facial expressions in real-time using a standard webcam Dig

转载于:https://www.cnblogs.com/oiramario/archive/2012/06/14/2548917.html

VS2010每次编译都重新编译整个工程的解决方案

在使用VS2010编译C程序的时候&#xff0c;每次修改工程中的某一个文件&#xff0c;点击“生成-仅用于项目-仅生成**”时&#xff0c;往往都是整个工程都需要重新编译一遍。由于这个工程代码量太大&#xff0c;每次编译完成都需要将近10分钟左右的时间编译。最烦人的时候是当编译…

马尔科夫链算法

这里介绍的马尔科夫链算法实现的功能是&#xff1a;读入一段英文文本&#xff0c;构造出由这个文本中语言使用情况而形成的统计模型&#xff0c;然后根据统计模型随机输出另一段文本。 马尔科夫链算法的基本思想是&#xff1a;将输入想象成一些相互重叠的短语构成的序列&#x…

Flutter中的BuildContext、Element、Key和RenderObject

学习Flutter不仅仅是学各Widget的使用&#xff0c;能堆叠出UI就行了&#xff0c;要多去学习底层的一些实现原理&#xff0c;尽量做到知其所以然。这也是区分程序员等级的一个参考指标。 在学习Flutter过程中&#xff0c;对BuildContext、Key、Element、RenderObject不是很了解…

Caffe的loss layer(转)

英文可查&#xff1a;地址 1.SoftmaxWithLoss 对一对多的分类任务计算多项逻辑斯蒂损失&#xff0c;并通过softmax传递预测值&#xff0c;来获得各类的概率分布。该层可以分解为SoftmaxLayerMultinomialLogisticLossLayer&#xff0c;但它的梯度计算在数值上更为稳健。在测试时…