【老孟Flutter】为什么 build 方法放在 State 中而不是在 StatefulWidget 中

老孟导读:此篇文章是生命周期相关文章的番外篇,在查看源码的过程中发现了这一有趣的问题,欢迎大家一起探讨。

Flutter 中Stateful 组件的生命周期:http://laomengit.com/blog/20201227/Stateful%E7%BB%84%E4%BB%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.html

Flutter 中与平台相关的生命周期:http://laomengit.com/blog/20201227/%E7%9B%B8%E5%85%B3%E5%B9%B3%E5%8F%B0%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.html

博客中还有更多精彩文章,也欢迎加入 Flutter 交流群。

灵活性

build 方法放在 State 中比放在 StatefulWidget 中更具灵活性,比如说,AnimatedWidgetStatefulWidget 的子类,AnimatedWidget 是一个抽象类,其中有一个 Widget build(BuildContext context) 的抽象方法,此方法需要子类重写,AnimatedWidget 源代码如下:

abstract class AnimatedWidget extends StatefulWidget {  ...  /// Override this method to build widgets that depend on the state of the  /// listenable (e.g., the current value of the animation).  @protected  Widget build(BuildContext context);  /// Subclasses typically do not override this method.  @override  _AnimatedState createState() => _AnimatedState();  ...}

删除了一些代码,保留了重点代码。

试想一下,如果 build 方法放在 StatefulWidget 中,则 AnimatedWidget 中的 build 方法需要带一个 State 参数,如下:

abstract class AnimatedWidget extends StatefulWidget {  ...  /// Override this method to build widgets that depend on the state of the  /// listenable (e.g., the current value of the animation).  @protected  Widget build(BuildContext context, AnimatedState state);  /// Subclasses typically do not override this method.  @override  _AnimatedState createState() => _AnimatedState();  ...}

但 AnimatedState 是内部实现,并不需要开放给外部(开发者),外部也不需要知道 AnimatedState 的内部实现。

闭包 this 指向异常

假设 build 方法在 StatefulWidget 中,StatefulWidget 的子类写法如下:

class MyWidget extends StatefulWidget {  final Color color;  @override  Widget build(BuildContext context, MyWidgetState state) {    print('${this.color}');    return Container();  }}

此时的 this 指向的是 MyWidget 的实例,然后父组件改变颜色,重新构建 MyWidget 组件,前一个 MyWidget 的实例中的 this 依然指向前一个 MyWidget 的实例,颜色并未发生变化。

如果 build 方法在 State 中,代码如下:

class MyWidget extends StatefulWidget {  final Color color;  const MyWidget({Key key, this.color}) : super(key: key);    @override  _MyWidgetState createState() => _MyWidgetState();}class _MyWidgetState extends State<MyWidget> {  @override  Widget build(BuildContext context) {    print('${widget.color}');    return Container();  }}

同样,父组件改变颜色,重新构建 MyWidget 组件,此时框架更新了 State 对象的 widget 属性的引用,新的 MyWidget 实例和 $ {widget.color} 将显示绿色。

性能

有状态的组件包含StatefulWidget 和 State,当有状态组件的配置发生更改时,StatefulWidget 将会被丢弃并重建,而 State 不会重建,框架会更新 State 对象中 widget 的引用,这极大的减轻了系统重建有状态组件的工作。

此方式对动画来说极为重要,由于 State 不会被重建,保留了前面的状态,不断的根据前一个状态计算下一个状态并重建其widget,达到动画的效果。

(0)

相关推荐

  • 【老孟Flutter】如何提高Flutter应用程序的性能

    首先 Flutter 是一个非常高性能的框架,因此大多时候不需要开发者做出特殊的处理,只需要避免常见的性能问题即可获得高性能的应用程序. 重建最小化原则 在调用 setState() 方法重建组件时, ...

  • Flutter 学习

    一.认识Fluter 几乎完全还原手机app,相当于原生app. 二.环境搭建(Windows) Windows 7以上64位系统,磁盘空间大于3个G,因为要安装模拟虚拟机 1.java环境的安装,下 ...

  • 半小时带你入门 Flutter

    前端技术优选 昨天 以下文章来源于全栈前端精选 ,作者Nealyang 由于微信外链限制,推荐阅读等链接无法点击,可点击阅读原文跳转至原文,查看外链. 国庆后面两天在家学习整理了一波flutter,基 ...

  • 【老孟Flutter】源码分析系列之InheritedWidget

    老孟导读:这是2021年源码系列的第一篇文章,其实源码系列的文章不是特别受欢迎,一个原因是原理性的知识非常枯燥,我自己看源码的时候特别有感触,二是想把源码分析讲的通俗易懂非常困难,自己明白 和 让别人 ...

  • 【老孟Flutter】2020年总结

    2020年是我经历的最不平凡的一年,这一年有遗憾.有收获,有感概,也有庆幸,庆幸自己还活着. 用一句话总结自己的2020,忙并收获着,累并快乐着. <Flutter 实战入门> <F ...

  • 【老孟Flutter】41个酷炫的 Loading 组件库

    老孟导读:目前 loading 库中包含41个动画组件,还会继续添加,同时也欢迎大家提交自己的 loading 动画组件或者直接微信发给我也可以. Github 地址:https://github.c ...

  • 2021高清版:如何查询“老赖”的财产?方法都在这

    来源:法务之家俗话说"有人的地方就有江湖有江湖的地方就有债务有债务的地方就有"老赖"人分三六九等肉有五花三层"老赖"也是有级别区分的 初级老赖特点:欠 ...

  • 气虚,血虚,阴虚,阳虚,有何不同?老中医教你调理方法,照着学

    在生活中,很多人会存在体虚,但是很多人无法判断自己是哪种虚弱,不同的体质虚弱,治疗的调理的方式也不一样,若是补错了,反而不利于健康,有的体质需要中药调理,但是用法却又不一,身体常见的体虚症状有,气虚, ...

  • 深度解析新老瓷器特征及做旧方法。

    随着是改革开放这几十年,民间收藏元明二朝出土的瓷器越来越普遍,但由于目前市场机制及专家队伍的混乱: 1.众多奸商利用收藏者的捡漏心理,大量造假贩假, 在"出土器"上大做文章,编故事 ...

  • 空调设计中,各类风口的选用遵循什么原则?老设计师道出选型方法

    空调设计中,各类风口的选用遵循什么原则?老设计师道出选型方法

  • 浅谈“老”哥瓷鉴定的方法

    收藏家都有一个梦,在梦中与自己梦寐以求的东西相遇,相知,相守.作为瓷器收藏家而言,宋瓷就好像喜马拉雅,而五大名窑则好似珠穆朗玛.特别是五大名窑中的汝窑,官窑,哥窑,更是难得一见.相比而言,均窑定窑则存 ...