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

本文深入探讨Flutter框架中StatefulWidget与State的设计理念,解释为何build方法位于State而非StatefulWidget中,涉及构建函数的位置如何影响性能及避免错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官网中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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值