官网中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上的构建函数中定义了一个闭包,那么该闭包将隐式捕获this
,this
就是当前的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