程序地带

【老孟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 中更具灵活性,比如说,AnimatedWidget 是 StatefulWidget 的子类,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,达到动画的效果。


交流

老孟Flutter博客(330个控件用法+实战入门系列文章):http://laomengit.com


欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:




版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/mengqd/p/14274589.html

随机推荐

linux for + sed

foriin{B,C,D,E,F};docpMtSnpA.shMtSnp${i}.shsed-i's/mtDNA/M24/g'MtSnp${i}.shsed-i"s/A.1/...

离子回旋 阅读(984)

七、Docker Compose

1.概述官网地址:https://docs.docker.com/compose/Compose是用于定义和运行多容器Docker应用程序的工具。通过Compose,您可以...

辰小诺 阅读(755)

Hanlp自定义字典(文件) java

Hanlp自定义字典(文件)java1.idea需要更改的地方位置:Hanlp.properties文件要放在resources目录下然后更改hanlp.pr...

Java叶 阅读(240)

Java语言基础

Java语言基础

二、Java语言基础2.1变量概念:计算机内存中的一块存储空间,是存储数据的基本单元组成:数据类型-变量名:值Java是强类型语言,...

Richard_lca 阅读(951)

读取XML文件时,总报“前言中不允许有内容”

idea读取XML文件时,总报“前言中不允许有内容”错误。经检查,XML文件格式、内容没有错误。而且这几个xml文件都是今天才生成的,查了一下是因为编码格式的...

b--d 阅读(108)