前言
如何快速高效的掌握一门知识,建议先阅读下这篇文章关于学习的一些看法。
Flutter渲染原理系列文章:
Flutter渲染原理系列之构建Widget树
一、Widget概念
1、定义:
Widget
是FLutter
中构建
用户界面的基本单元
。
2、特点:
- 不可变性:
Widget
是不可变的
,其内部属性都是final
修饰的,一旦创建不能改变。 - 描述性:描述了给定其当前
状态
时,视图应该看起来像什么。 - 组合性:可以
组合
在一起形成更复杂的UI
组件。 - 响应式:当其
状态
发生变化时,Flutter
框架会重建UI
。
3、补充说明:
Widget
不仅可以看着是UI
元素,还可以表示功能组件,比如用于App
主题数据传递的Theme
、用于手势检测的GestureDetector
等。Widgets
通过布局组合形成一种层次结构关系。每个Widget
都嵌套在其父级的内部,并可以通过父级接收上下文
。- 从
根布局
(托管Flutter
应用的容器,通常是MaterialApp
或CupertinoApp
)开始,自上而下都是这样的结构。
二、Widget源码说明
/// 1. Describes the configuration for an [Element].
2. @immutable
abstract class Widget extends DiagnosticableTree {
3. final Key? key;
@protected
@factory
4. Element createElement();
5. static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
}
上述代码中,只保留了核心属性及方法,其他暂不讨论,下面进行详细说明。
1、类功能描述
:
Widget
的功能是描述
一个UI
元素的配置信息
。- 换言之,
Widget
并不是最终绘制在屏幕上的显示元素。 配置信息
:即Widget
接收的参数
,如Text
,其内容
、对齐方式
、文本样式
等皆是配置信息
。
2、@immutable
:
- 该注解表示
Widget
是不可变的
,这会限制Widget
中的属性
必须是不可变的
(final
修饰)。 原因
:在Flutter
中, 如果属性变化
就会重建Widget
树,即新实例会替换旧的实例,所以允许其属性变化是无意义的。这也是其属性必须是final
的原因。
3、Key
:
Widget
的唯一标识
。- 主要用于
build
时判断两个Widget
是否可以更新,在canUpdate
方法中使用。
4、createElement()
:
Widget
是抽象类,该方法使用@protected
修饰,意味着子类必须重写该方法。- 主要用于创建一个与
Widget
关联的Element
。 Element
是Widget
的运行时表示,可管理Widget
在树中的位置
,同时负责创建和更新RenderObject
。- 一个
Widget
可对应多个Element
,原因是一个特定的Widget
实例可以被复用,并出现在Widget
树的不同位置,因此可以有多个对应的Element
。
5、canUpdate(...)
:
- 用于判断两个
Widget
是否可以更新。 - 如果两个
Widget
的类型
和Key
相同,则认为可以更新。 - 该方法用于
Widget
树的比较
和更新
过程。
三、StatelessWidget
abstract class StatelessWidget extends Widget {
const StatelessWidget({ super.key });
/// Creates a [StatelessElement] to manage this widget's location in the tree.
@override
StatelessElement createElement() => StatelessElement(this);
@protected
Widget build(BuildContext context);
}
Widget
的核心子类之一,无状态
。createElement()
:- 重写了父
widget
中的方法。返回一个StatelessElement
对象,该对象间接继承自Element
类,与StatelessWidget
相对应。 StatelessElement
负责管理Widget
在树中的位置
,同时负责创建和更新RenderObject
。
- 重写了父
build(BuildContext context)
:- 子类需要实现该方法。
- 它接受一个
BuildContext
参数,并返回一个Widget
。 - 用于构建
UI
,返回的Widget
描述了UI
的当前状态
。
StatelessWidget
是用于构建无状态
的UI
的基类
,它通常在build
方法中通过嵌套
其他Widget
来构建UI
,在构建过程中会递归
的构建其嵌套的Widget
。
四、StatefulWidget
abstract class StatefulWidget extends Widget {
const StatefulWidget({ super.key });
/// Creates a [StatefulElement] to manage this widget's location in the tree.
@override
StatefulElement createElement() => StatefulElement(this);
@protected
@factory
State createState();
}
Widget
的核心子类之一,有状态
。createElement()
:- 重写了父
widget
中的方法。返回一个StatefulElement
对象,该对象间接继承自Element
类,与StatefulWidget
相对应。 StatefulElement
负责管理Widget
在树中的位置
,同时负责创建和更新RenderObject
。
- 重写了父
createState()
:- 子类需要实现该方法,该方法返回一个
State
对象。 - 用于创建和
StatefulWidget
相关的状态(State
),具有一一对应的关系。 - 它在
StatefulWidget
的生命周期中可能被多次调用。
- 子类需要实现该方法,该方法返回一个
StatefulWidget
用于构建具有状态
的UI
的基类
。它通过createState
方法返回一个State
对象来管理状态。通过State
对象的setState
方法来通知框架状态发生变化,并触发UI
的重建。
五、Widget树是如何构建的?
1、准备Widget
树:
- 应用程序的
UI
是由一个或多个Widget
组成的树形结构
。 - 每个
Widget
都可以包含子Widget
,形成一个层次结构
。
2、构建Widget
树:
- 当
Widget
树准备好后,Flutter
引擎会调用build
方法来构建Widget
树。 - 每个
Widget
的build
方法返回一个Widget
,这个Widget
描述了UI
的当前状态。
此构建对应于第一节中渲染原理
图中的build
阶段中的前期准备。
六、总结
理解Widget
相关概念及其源码对于深入了解Flutter
的UI
构建机制非常重要。希望这些信息能帮助你更好地理解Widget
的工作原理
。
码字不易,记得 关注 + 点赞 + 收藏 + 评论