Flutter核心原理(Flutter UI 框架(Framework)+Element、BuildContext和RenderObject )

什么是UI框架?

UI框架是在特定平台上实现快速开发图形用户界面(GUI)的框架。它解决了如何基于基础的图形API(如Canvas)来封装一套高效创建UI的工具集的问题。
每个平台的UI框架实现原理基本相通,无论是Android还是iOS,它们将用户界面展示到屏幕的流程都是类似的。UI框架的作用是简化开发人员在特定平台上创建GUI的过程,提供高效且易于使用的工具和组件,使开发者能够快速构建各种用户界面。

硬件绘图基本原理

屏幕显示图像的基本原理是每一个像素点可以发出多种颜色,并以固定的频率刷新图像。计算机系统中,CPU将计算好的显示内容提交给GPU,GPU渲染后放入帧缓冲区,然后视频控制器按照同步信号从帧缓冲区取帧数据传递给显示器显示。CPU主要用于基本数学和逻辑计算,而GPU主要执行和图形处理相关的复杂的数学,如矩阵变化和几何计算,GPU的主要作用就是确定最终输送给显示器的各个像素点的色值。

操作系统绘制API的封装

操作系统屏蔽了底层硬件操作,并提供封装后的API供应用调用。为了简化开发,GUI编程语言会在操作系统之上再封装一层UI框架,将操作系统原生API封装成一个编程框架和模型。这些UI框架定义了开发规则来描述UI,如UI树结构和操作原则。常见的UI框架有Android SDK和iOS的UIKit。

Flutter UI框架

可以实现一个UI框架,使用同一种编程语言开发,然后在底层通过中间层来适配不同操作系统的API。这样就可以使用同一套代码编写跨平台的应用。Flutter正是采用了这种原理,它提供了一套Dart API,在底层使用OpenGL这种跨平台的绘制库来调用操作系统的API。由于使用原生渲染,并且可以优先使用特定操作系统提供的图形库(如Metal),因此Flutter具有接近原生的性能。

对于应用开发者而言,Flutter采用组合和响应式的开发标准。开发者通过组合其他Widget来构建UI界面,当UI需要改变时,不直接修改DOM,而是通过更新状态,让Flutter UI框架重新构建UI。

Element

在Flutter的UI系统中,存在三棵树:Widget树、Element树和渲染树。它们之间的关系可以概括为以下几点:

  1. Widget树:Widget树是由Flutter应用程序的各种Widget组成的层次结构。Widget是不可变对象,描述了应用程序界面的基本组件和布局。Widget树描述了应用程序界面的结构和层级关系。

  2. Element树:Element树是由Widget树生成的,它是Widget在UI树中的具体位置的实例化对象。Element是可变对象,与Widget对应,负责管理与Widget相关的状态和生命周期。Element树和Widget树的结构一一对应。

  3. 渲染树:渲染树是由Element树生成的,它包含了实际用于布局和绘制的RenderObject对象。RenderObject是通过创建相应的RenderObject并将其与Element关联来表示UI元素的布局和渲染。渲染树负责将UI元素根据布局约束进行排列,并最终绘制到屏幕上。

总结起来,Widget树描述了应用程序界面的结构,Element树管理着与Widget相关的状态和生命周期,渲染树负责将UI元素进行布局和绘制。它们之间的关系是Widget树生成Element树,而Element树又生成渲染树。这三棵树共同协作,构成了Flutter的UI系统。
在这里插入图片描述
接下来看一看Element的生命周期
4. 创建阶段:在Framework调用Widget的createElement方法时,会创建对应的Element实例。
5. 挂载阶段:在Framework调用element的mount方法时,会创建与element相关联的RenderObject对象,并将其添加到渲染树中指定的位置。此时,element进入"active"状态,可以显示在屏幕上。
6. 更新阶段:当父Widget的配置数据发生变化时,需要重新构建对应的Element树。在更新前,会尝试复用旧树上相同位置的element。如果可以复用,则更新旧的Element;否则,创建一个新的Element。
7. 移除阶段:当祖先Element决定移除element时,会调用deactivateChild方法将其从渲染树中移除,并将element状态变为"inactive"。处于"inactive"状态的element不会显示在屏幕上,在当前动画最后一帧结束前保留。
8. 卸载阶段:如果"inactive"态的element未能重新变为"active"状态,在动画执行结束后,会调用unmount方法彻底移除该element,状态变为"defunct",不再插入到树中。
9. 重新插入阶段:如果element要重新插入到其他位置,如拥有一个全局复用元素的GlobalKey,会先将element从现有位置移除,然后调用activate方法,并将其renderObject重新attach到渲染树。

BuildContext

BuildContext是Flutter框架中的一个抽象接口类,用于表示构建Widget树的上下文信息。它作为参数传递给StatelessWidget和StatefulWidget的build方法。

具体来说,在StatelessWidget和StatefulWidget的build方法中,BuildContext对象实际上是对应的StatelessElement和StatefulElement对象。这些Element对象是构成Widget树的基本单元。

BuildContext提供了许多方法和属性,可以用于获取和操作当前Widget树中的相关信息。例如,通过Theme.of(context)可以获取主题数据,通过Navigator.push(context, route)可以入栈新的路由,通过Localizations.of(context, type)可以获取本地化信息等。此外,还可以使用context.size获取上下文的大小,使用context.findRenderObject()查找当前或最近的一个祖先RenderObject。

需要注意的是,BuildContext对象只在构建Widget树的过程中有效,并且不能在构建完成后持久使用。在构建过程中,如果需要保留一些需要持久使用的信息,需要将其保存在其他合适的地方。

总之,BuildContext是Flutter中用于构建Widget树的上下文对象,通过它可以方便地获取和操作当前Widget树中的相关信息,而具体的实现类是对应的Element对象。

因此可以回答下面问题:为什么build方法的参数不定义成Element对象,而要定义成BuildContext ?

在Flutter框架中,build方法的参数是BuildContext而不是Element对象的原因是为了提供更好的封装和抽象,使得开发者能够更方便地构建用户界面。

BuildContext是一个上下文对象,它包含了当前Widget在Widget树中位置的相关信息。它提供了一种访问父级、子级和兄弟级Widget以及其他相关功能的方式。通过BuildContext,我们可以访问到诸如主题、局部化(Localizations)、媒体查询(MediaQuery)等与UI构建相关的信息。

相比之下,Element对象则是Flutter框架内部使用的概念,代表着Widget在渲染树中的一个实例。每个Element对象都对应着特定类型的Widget,并负责管理与该Widget相关的状态、生命周期和绘制等操作。

通过将BuildContext作为build方法的参数,Flutter在内部进行了封装,隐藏了底层的Element细节,使得开发者能够更专注于构建UI逻辑,无需关心元素层级和复杂的管理逻辑。它也使得Flutter能够更容易进行性能优化和重建UI的工作。

总结起来,将BuildContext作为build方法的参数,是为了提供更高级别的抽象和封装,简化UI构建的逻辑,并隐藏底层的Element实现细节。这有助于提高开发效率和代码可读性,并使得Flutter框架更易于优化和演进。

RenderObject

RenderObject是Flutter渲染树中的对象,承担着实现事件响应和渲染管线中布局、绘制、层合成及上屏等功能的责任。它通过parent和parentData属性与父节点及布局信息进行关联,保存布局信息用于后续的绘制过程。RenderObject类定义了一套基础的布局和绘制协议,但没有具体的子节点模型、坐标系统和布局协议。

为了解决这些问题,Flutter提供了RenderBox和RenderSliver两个类,它们都继承自RenderObject。RenderBox基于盒模型布局和笛卡尔坐标系,实现了常见的布局方式;RenderSliver则基于按需加载模型,用于处理可滚动场景下的大量数据。这两个类通过继承RenderObject扩展了具体的子节点模型和布局协议,为Flutter提供了灵活且高效的渲染机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值