【老孟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】:
![]() |
![]() |
【老孟Flutter】为什么 build 方法放在 State 中而不是在 StatefulWidget 中的更多相关文章
- 【老孟Flutter】源码分析系列之InheritedWidget
老孟导读:这是2021年源码系列的第一篇文章,其实源码系列的文章不是特别受欢迎,一个原因是原理性的知识非常枯燥,我自己看源码的时候特别有感触,二是想把源码分析讲的通俗易懂非常困难,自己明白 和 让别人 ...
- 【老孟Flutter】Stateful 组件的生命周期
老孟导读:关于生命周期的文章共有2篇,第一篇是介绍 Flutter 中Stateful 组件的生命周期. 博客地址:http://laomengit.com/blog/20201227/Statefu ...
- 【老孟Flutter】Flutter 中与平台相关的生命周期
老孟导读:关于生命周期的文章共有2篇,一篇(此篇)是介绍 Flutter 中Stateful 组件的生命周期. 第二篇是 Flutter 中与平台相关的生命周期, 博客地址:http://laomen ...
- 【老孟Flutter】如何提高Flutter应用程序的性能
首先 Flutter 是一个非常高性能的框架,因此大多时候不需要开发者做出特殊的处理,只需要避免常见的性能问题即可获得高性能的应用程序. 重建最小化原则 在调用 setState() 方法重建组件时, ...
- 【老孟Flutter】2021 年 Flutter 官方路线图
老孟导读:这是官方公布的2021年路线图,向我们展示了2021年 Flutter 的主要工作及计划. 原文地址:https://github.com/flutter/flutter/wiki/Road ...
- 【老孟Flutter】Flutter 2的新功能
老孟导读:昨天期待已久的 Flutter 2.0 终于发布了, Flutter Web和Null安全性趋于稳定,Flutter桌面安全性逐渐转向Beta版! 原文链接:https://medium.c ...
- 【老孟Flutter】6种极大提升Flutter开发效率的工具包
老孟导读:本文介绍6种极大提升Flutter开发效率的工具包. [1] 强大的日志软件包 在开发 Flutter 的过程中打印日志是常用的调试方式之一,但 Flutter 内置的日志打印非常简单,下面 ...
- 【老孟Flutter】自定义文本步进组件
交流 老孟Flutter博客(330个控件用法+实战入门系列文章):http://laomengit.com 欢迎加入Flutter交流群(微信:laomengit).关注公众号[老孟Flutter] ...
- 【老孟Flutter】41个酷炫的 Loading 组件库
老孟导读:目前 loading 库中包含41个动画组件,还会继续添加,同时也欢迎大家提交自己的 loading 动画组件或者直接微信发给我也可以. Github 地址:https://github.c ...
随机推荐
- java视频格式转换
项目中需要对各种视频格式转码为mp4格式,试了好多办法,最后使用ffmpeg 工具完美转码,ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) 链接 ...
- vs2015常用快捷键大全
1.回到上一个光标位置/前进到下一个光标位置 1)回到上一个光标位置:使用组合键"Ctrl + -"; 2)前进到下一个光标位置:"Ctrl + Shift + - &q ...
- 使用MySQL Shell创建MGR
本篇知识点: 配置MGR所需的参数 使用MySQL Shell配置MGR shell.connect() var 设定临时变量 dba.createCluster() dba.getCluster() ...
- 三、LoadRunner卸载
由于安装的时候没看提前了解清楚,LoadRunner社区版只能模拟50个用户,满足不了工作需求,删了重装吧. 1-打开"控制面板"-点击"卸载程序" 2-找到H ...
- 【JVM专题】JVM从概述到调优图文详解,含思维脑图深度剖析!
JVM概述 JVM 是一种用于计算机设备的规范,它是一个虚构的计算机的软件实现,简单的说,JVM 是运行 byte code 字节码程序的一个容器. 它有一个解释器组件,可以实现 JAVA 字节码和计 ...
- Spring @Scheduled Annotation
1.Overview 这里我们将会学习Spring @Scheduled 标签,了解它是如何配置,如何设置定时任务. 关于它的使用,有两点简单的规则需要记住: ※它的方法应该是一个void返回值类型 ...
- ceph工作原理及安装
一.概述 Ceph是一个分布式存储系统,诞生于2004年,最早致力于开发下一代高性能分布式文件系统的项目.随着云计算的发展,ceph乘上了OpenStack的春风,进而成为了开源社区受关注较高的项目之 ...
- js第二次作业——2019.10.16
第一题:完成省城市的三级联动(包括湖南省),附代码和效果图. 1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 </head> ...
- matplotlib的学习9-bar柱状图
import matplotlib.pyplot as plt import numpy as np ''' 向上向下分别生成12个数据,X为 0 到 11 的整数 ,Y是相应的均匀分布的随机数据. ...
- Open_basedir绕过
Open_basedir绕过 一.基础知识 open_basedir是php.ini中的一个配置选项,它可将用户访问文件的活动范围限制在指定的区域, 假设open_basedir=/home/wwwr ...