乐趣区

关于前端:Flutter灵魂拷问为什么-build-在-State-中而不是在-StatefulWidget

这一篇想跟大家聊一个细节问题:为什么 build() 不在 StatefulWidget 外面而在 State 外面呢?

通常咱们写一个无状态组件 StatelessWidget 是这样的:

class Foo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {return Container();
  }
}

有状态组件 StatefulWidget 把可变的状态变量放到了 State 对象中,参照 StatelessWidget 的形式,把 build() 办法放到 StatefulWidget 中行不行?比方这样:

class Foo extends StatefulWidget {
  @override
  Widget build(BuildContext context, State state) {return Container();
  }
}

看起来如同没啥问题,须要状态值就从 state 变量去取就好了,放在 StatefulWidget 中还合乎习惯跟 StatelessWidget 是相似的。Fultter 没有这样去做的起因次要是从 代码的封装和灵活性 来思考的。

咱们晓得 Flutter 中的组件 Widget 是能够继承的。一旦咱们把某一种通用状态逻辑的 StatefulWidget 子类化,就会发现如果把 build() 放在 StatefulWidget 中将是一个不合理的实现形式。

这里举一个例子,比方显式动画组件的抽象类 AnimatedWidget,它外部的 State 负责解决了动画的监听事件和主动调用 setState 来使组件重绘。开发者在应用时须要重写 build() 来展现本人的 UI,如果像下面代码示例里 build() 在 StatefulWidget 中,那 AnimatedWidget 就必须在 build() 办法中把抽象类的 state 对象传递给子类。然而你应该发现了这里 state 是 AnimatedWidget 父类外部应用和实现的,子类不应该理解细节。而将 build() 放在 State 中则不会呈现这样的问题,AnimatedWidget 申明一个 build() 让子类使用者去实现,而后在本人的 State 中去调用 widget.build(),代码的封装和灵活性都显著好多了。

这里再顺带一提官网文档里讲的那个闭包捕捉的问题解释,说实话我感觉有点牵强例子没举好。官网文档在这里:https://api.flutter.dev/flutt…

有点意思的是我找到了过后对于这个问题的探讨:https://github.com/flutter/fl…

有人提出了和我一样的疑难:当父更新时,子组件 Widget 会从新创立是个新实例,如果说有闭包也是新的闭包哪来旧闭包问题一说?如下:

提出这个闭包问题的作者回复说这取决于是怎么用这个旧闭包的,有可能这个旧闭包被另外一个对象持有了。也没举出理论的场景和例子,有点牵强。

综上所述,build() 在 State 中的确是正当的。Flutter 中有很多这种设计上的衡量思考,值得好好学习哇~

退出移动版