【老孟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的布局方法
重点是什么? Widgets 是用于构建UI的类. Widgets 用于布局和UI元素. 通过简单的widget来构建复杂的widget Flutter布局机制的核心就是widget.在Flutter ...
- RPC 编程 使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大、最高效的方法之一。它为在分布式计算环境中运行的几乎所有应用程序提供基础。
RPC 编程 使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大.最高效的方法之一.它为在分布式计算环境中运行的几乎所有应用程序提供基础.本文介绍 RPC 客户机和服务器之间基本的事件流 ...
- vuex this.$store.state.属性和mapState的属性中的一点点区别
做泰康公众号的项目时候有一个需求创建公众号的时候后台有一个社区id提供给后台展现人员和部门,在群发消息时候也要给后台一个社区id只不过获取社区的id接口和上一个不是一样的,本来在页面中写了两个sele ...
- Nodejs:npm run build之后,dist\index.html页面在火狐中可以正常显示登录页面并登录成功,在Chrome中可以正常显示登录页面,登录失败
问题描述:Nodejs:npm run build之后,dist\index.html页面在火狐中可以正常显示登录页面并登录成功,在Chrome中可以正常显示登录页面,登录失败 解决方法:将打包后的d ...
- 两种方法实现用CSS切割图片只取图片中一部分
切割图片这里不是真正的切割,只是用CSS取图片中的一部分而已,主要有两种方式,一是做为某一元素的背景图片,二是用img元素的属性.下面有个不错的示例,大家可以参考下 切割图片这里不是真正的切割,只是用 ...
- 关于phpcms中模块_tag.class.php中的pc_tag()方法的含义
关于phpcms中模块_tag.class.php中的pc_tag()方法的含义: 在phpcms系统中自己写后台模块,要在前台模板中显示出来须要在\phpcms\modules\自定义 ...
- iphone下元素放在了一个position: fixed的div中无法点击
网上的说法是这样的: iphone的浏览器有这么一个bug, 当你使用锚定或滚动页面后, 你会发现某些东西不能点击了! 如果你的这个“东西”放在了一个position: fixed的div中, 那么你 ...
- android开发中关于继承activity类中方法的调用
android开发中关于继承activity类中的函数,不能在其他类中调用其方法. MainActivity.java package com.example.testmain; import and ...
- Java 访问限制符 在同一包中或在不同包中:使用类创建对象的权限 &; 对象访问成员变量与方法的权限 &; 继承的权限 &; 深入理解protected权限
一.实例成员与类成员 1. 当类的字节码被加载到内存, 类中类变量.类方法即被分配了相应内存空间.入口地址(所有对象共享). 2. 当该类创建对象后,类中实例变量被分配内存(不同对象的实例变量互不相同 ...
- HTML5中的data-*属性和jQuery中的.data()方法使用
原文地址链接:http://blog.csdn.net/fly_zxy/article/details/50687691: HTML5中的data-*属性 我们往往会根据需要在HTML标记上添加自定义 ...
随机推荐
- swift 中delegate的使用
今天写了delegate,遇到以下问题: 这里protocol的写法有问题,如果delegate指向一个实现了某个协议对象的引用,在oc里是这样写delegate的类型 id<protocol& ...
- Html笔记(五)表格
表格标签: <table> 组成: 标题标签: <caption>给表格提供标题. 表头标签: <th> ,一般对表格的第一行或者第一列进行格式化,就是粗体显示,并 ...
- 你知道用AngularJs怎么定义指令吗?
前言 最近学习了下angularjs指令的相关知识,也参考了前人的一些文章,在此总结下. 欢迎批评指出错误的地方. Angularjs指令定义的API AngularJs的指令定义大致如下 ang ...
- android 随手记 自定义广播通知栏
自定义通知栏图标?不是很简单么.自定义布局都不在话下! 是的,有xml布局文件当然一切都很简单,如果不给你布局文件用呢? 听我慢慢道来! 首先怎么创建一个通知呢? 1.new 一个 Notificat ...
- Spring AOP切面的时候参数的传递
Spring AOP切面的时候参数的传递 Xml: <?xml version="1.0" encoding="UTF-8"?> <beans ...
- 自学Python6.4-内置模块(2)
自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...
- C# 读取Excel和DBF文件
//获excel中多个sheet中的数据 /// <summary> /// 读取导入Excel文件内容 /// </summary> /// <param name=& ...
- 【LeetCode每天一题】Fibonacci Number(斐波那契数列)
The Fibonacci numbers, commonly denoted F(n) form a sequence, called the Fibonacci sequence, such th ...
- 3.The significance of Books 书本的意义
3.The significance of Books 书本的意义 (1)A bookless life is an imcomplete life.Books influence the depth ...
- 项目中的一个分页功能pagination
项目中的一个分页功能pagination <script> //总页数 ; ; //分页总数量 $(function () { // $("#pagination"). ...