Flutter渲染原理系列之构建Widget树

前言

如何快速高效的掌握一门知识,建议先阅读下这篇文章关于学习的一些看法

Flutter渲染原理系列文章:

Flutter渲染原理系列之开篇问题

Flutter渲染原理系列之构建Widget树

Flutter渲染原理系列之构建Element树~敬请期待

Flutter渲染原理系列之构建RenderObject树~敬请期待

Flutter渲染原理系列之合成Layer树~敬请期待

Flutter渲染原理系列之GPU渲染~敬请期待

Flutter渲染原理系列之屏幕刷新(Async)~敬请期待

Flutter渲染原理系列之runApp执行流程~敬请期待

一、Widget概念

定义

  • WidgetFLutter定义构建 用户界面的基本单元

补充说明

  • Widget不仅可以看着是UI元素,还可以表示功能组件 ,比如用于App主题数据传递的Theme、用于手势检测的GestureDetector等。
  • Widgets通过布局组合 形成一种层次结构关系 。每个Widget都嵌套在其父级的内部,并可以通过父级接收上下文
  • 根布局 (托管Flutter应用的容器,通常是MaterialAppCupertinoApp)开始,自上而下都是这样的结构。

特点

  • 不可变性 :每个Widget都是不可变的 ,其内部属性都是final修饰的,这意味着一旦创建不能改变。
  • 描述性Widget描述了给定其当前配置状态时,视图应该看起来像什么。
  • 组合性Widget可以组合在一起形成更复杂的UI组件。
  • 响应式 :当Widget的状态发生变化时,Flutter框架会重新构建UI

二、Widget源码说明

dart 复制代码
/// 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 @factory两注解修饰,意味着子类必须重写该方法。
  • 创建一个与Widget关联的Element
  • ElementWidget的运行时表示,可管理Widget在树中的位置 ,同时负责创建更新 RenderObject
  • 一个widget可对应多个Element,原因是一个特定的Widget实例可以被复用,并出现在Widget树的不同位置,因此可以有多个对应的Element

5、canUpdate(...)

  • 用于判断两个Widget是否可以更新。
  • 如果两个Widget类型Key相同,则认为可以更新。
  • 该方法用于Widget树的比较更新过程。

三、StatelessWidget

scala 复制代码
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

scala 复制代码
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树。
  • 每个Widgetbuild方法返回一个Widget,这个Widget描述了UI当前状态

此阶段对应第一节中渲染原理 图中的build阶段。

六、总结

理解Widget相关概念及其源码对于深入了解FlutterUI构建机制非常重要。希望这些信息能帮助你更好地理解Widget工作原理

码字不易,记得关注 + 点赞 + 收藏

相关推荐
bug丸4 分钟前
v8引擎垃圾回收
前端·javascript·垃圾回收
安全小王子5 分钟前
攻防世界web第三题file_include
前端
&活在当下&6 分钟前
ref 和 reactive 的用法和区别
前端·javascript·vue.js
百事老饼干9 分钟前
VUE前端实现防抖节流 Lodash
前端
web Rookie14 分钟前
React 高阶组件(HOC)
前端·javascript·react.js
云白冰27 分钟前
hiprint结合vue2项目实现静默打印详细使用步骤
前端·javascript·vue.js
葡萄架子35 分钟前
Python中的logger作用(from loguru import logger)
java·前端·python
Hi_MrXiao44 分钟前
前端实现图片压缩插件(image-compressorionjs)
前端
阿智@111 小时前
Node.js 助力前端开发:自动化操作实战
运维·前端·node.js·自动化
m0_748251721 小时前
前端入门之VUE--ajax、vuex、router,最后的前端总结
前端·vue.js·ajax