Flutter 核心原理 - UI 框架(UI Framework)
Flutter 既能保证很高的开发效率,又能获得很好的性能。
这两年 Flutter 技术热度持续提高,整个 Flutter 生态和社区也发生了翻天覆地的变化。目前Flutter 稳定版发布到了3.0,现在已经支持移动端、Web端和PC端,通过Flutter 开发的应用程序能够轻松的在各个平台迁移并获得很好的性能。另外,Flutter 在 Github Star 数上排名已经进入了前20,在跨端框架中已经成为稳稳的第一。
根据近几年实践统计,Flutter 相比原生开发,人效能提高近一倍,且性能可以接近原生。
Flutter 源起
Flutter 属于在实现三个跨端框架方向之一的“自绘UI + 原生”的范畴。在上一篇中也介绍过。
Flutter 实现一套自绘UI引擎,并拥有一套自己的 UI 布局框架。
得益于但Dart开发语言的JIT 运行方式支持动态化的。因此,在开发过程中 Flutter 的热重载可帮助开发者快速地进行测试、构建UI、添加功能并更快地修复错误。在 iOS 和 Android 模拟器或真机上可以实现毫秒级热重载,并且不会丢失状态。
Flutter 从上到下分为UI框架层、引擎层和嵌入层。开发者基本上都是与UI框架层打交道。
UI 框架
UI 框架(UI Framework)指基于一个操作系统和浏览器之上快速开发GUI(图形用户接口)的框架。通常来讲平台只提供非常基础的图形 API(Canvas),如画线、画几何图形等。
可以想象一下,如果没有UI 框架的封装而直接用 Canvas 来构建用户界面将会是怎样的一个体验和效率!
简单来讲, UI 框架解决的主要问题就是:如何基于基础的图形API(Canvas)来封装一套可以高效创建UI的框架。
各个平台 UI 框架的实现原理基本是相通的,在介绍Flutter UI框架之前,可以先了解平台图形处理的基本原理。操作系统(Android&IOS)图像绘图的基本原理-CSDN博客
Flutter UI框架
Android SDK封装了Android操作系统API,提供了一个“UI描述文件 XML+Java/Kotlin 操作 DOM”的UI 框架。iOS的 UIKit 对 View 的抽象也是一样的。他们都将操作系统API抽象成一个基础对象,然后再定义一套规则来描述UI,如UI树结构,UI 操作的单线程原则等。
如果可以使用同一种编程语言开发,在不同操作系统API上封装一个对上接口一致,对下适配不同操作系统的中间层。那么我们就可以使用同一套代码编写跨平台的应用了。
而Flutter的原理正是如此:它提供了一套Dart API,然后在底层通过OpenGL这种跨平台的绘制库(内部会调用操作系统API)实现了一套代码跨多端。
由于Dart API也是调用操作系统API,所以它的性能接近原生。
*注解:
- 虽然Dart是先调用了OpenGL,OpenGL才会调用操作系统API,但是这仍然是原生渲染,因为OpenGL只是操作系统API的一个封装库,它并不像WebView渲染那样需要 JavaScript 运行环境和CSS渲染器,所以不会有性能损失。
- Flutter 早期版本底层会调用 OpenGL 这样的跨平台库,但在 iOS 设备上苹果提供了专门的图形库Metal,使用 Metal可以在iOS上获得比OpenGL更好的绘图性能,因此Flutter后来在 iOS 上会优先调用 Metal ,只有当 Metal 不可用时才会降级到OpenGL。不过 Flutter 底层到底是调用的哪个库,作为应用开发者是不需要关注的,我们只需要知道调用的是原生的绘图接口,可以保证高性能即可。
FlutterUI框架
简单概括:组合+响应式。
在Flutter开发UI中,一切皆是Widget。我们要开发一个UI界面,需要组合不同Widget来实现。而当UI要发生变化时,我们不去直接修改DOM,而是通过更新状态State,让Flutter UI 框架来根据新的状态来重新构建UI。
先介绍一下BuildContext、RenderObject、Element
,它们是组成Flutter UI 框架的基石。
BuildContext
StatelessWidget
和StatefulWidget
的build
方法都会传一个BuildContext
对象。
Widget build(BuildContext context) {}
我们也知道,在很多时候我们都需要使用这个context
做一些事,比如:
Theme.of(context) //获取主题
Navigator.push(context, route) //入栈新路由
context.findRenderObject() //查找当前或最近的一个祖先RenderObject
那么BuildContext
到底是什么呢,查看其定义,发现其是一个抽象接口类:
abstract class BuildContext {...
}
那这个context
对象对应的实现类到底是谁呢?以StatelessElement
为例:
class StatelessElement extends ComponentElement {...@overrideWidget build() => widget.build(this);...
}
发现build
传递的参数是this
。这个BuildContext的实现类
就是StatelessElement
。
虽然StatelessElement
或StatefulElement
并没有实现BuildContext
接口,但它们继承自Element
类,而Element
类实现了BuildContext
接口:
class Element extends DiagnosticableTree implements BuildContext {...
}
结论:BuildContext
就是widget对应的Element。
所以,我们可以通过context
在StatelessWidget
和StatefulWidget
的build
方法中访问到Element
对象。
RenderObject
RenderObject
的主要职责是Layout布局和绘制。
所有的RenderObject
会组成一棵渲染树“Render Tree”。
RenderObject
就是渲染树中的一个对象,它可以实现事件响应以及布局、绘制、显示。
RenderObject
类本身实现了一套基础的布局和绘制协议。 它本身没有定义坐标系统和具体的布局协议。为此,Flutter框架提供了一个RenderBox 的盒模型布局和基于 Sliver 的按需加载模型。布局坐标系统采用笛卡尔坐标系,屏幕的(top, left)是原点。
一个Element
都对应一个RenderObject
,我们可以通过Element.renderObject
来获取。
Element
我们知道UI树其实是由一个个独立的Element节点构成。Element就是Widget在UI树具体位置的一个实例化对象。
所有Element的RenderObject构成一棵树,我们称之为”Render Tree“即”渲染树“。
UI框架的三棵树:Widget树、Element树、渲染树。
Element树根据Widget树生成,而渲染树又依赖于Element树。
从创建到渲染的流程是:根据Widget生成Element,然后创建相应的RenderObject
并关联到Element.renderObject
属性上,最后再通过RenderObject
来完成布局排列和绘制。
其实对于开发者来说只需要关注Widget树就行,Flutter框架已经将对Widget树的操作映射到了Element树上,这可以极大的降低复杂度,提高开发效率。
但是了解Element对理解整个Flutter UI框架是至关重要的,Flutter正是通过Element这个纽带将Widget和RenderObject关联起来。
了解Element层不仅会帮助读者对Flutter UI框架有个清晰的认识,而且也会提高自己的抽象能力和设计能力。
Element的生命周期
- Framework 调用
Widget.createElement
创建一个Element实例,记为element
element
调用所对应Widget的createRenderObject
方法创建与element
相关联的RenderObject对象。然后element.attachRenderObject
将renderObject
添加到渲染树。此时element
就处于“active”状态,就可以显示在屏幕上了。- 当有父Widget的配置数据改变时,同时其
State.build
返回的Widget结构与之前不同,就需要重新构建对应的Element树。此时Element会先尝试复用旧树上相同位置的element。通过调用Widget.canUpdate
方法判断newWidget
与oldWidget
的runtimeType
和key
是否同时相等,如果同时相等就返回true
复用旧Element。否则就创建新的Element。 - 当Widget树结构发生了变化,导致
element
对应的Widget被移除时,该祖先Element就会调用deactivateChild
方法来移除element。Framework会调用element.deactivate
方法,这时element
状态变为“inactive”状态。“inactive”态的element将不会再显示到屏幕。 - 如果
element
要重新插入到Element树其他的位置,Framework会先将element从现有位置移除,然后再调用其activate(
激活)
方法,将其renderObject
重新attach到渲染树。
相关文章:

Flutter 核心原理 - UI 框架(UI Framework)
Flutter 既能保证很高的开发效率,又能获得很好的性能。 这两年 Flutter 技术热度持续提高,整个 Flutter 生态和社区也发生了翻天覆地的变化。目前Flutter 稳定版发布到了3.0,现在已经支持移动端、Web端和PC端,通过Flutter 开发的…...

Hive优化
工作中涉及到优化部分不多,下面的一些方案可能会缺少实际项目支撑,这里主要是为了完备一下知识体系。 参考的hive参数管理文档地址:https://cwiki.apache.org/confluence/display/Hive/ConfigurationProperties 对于Hive优化,可以…...

React 的 diff 算法
React 的 diff 算法的演进。 在 React 16 之前,React 使用的是称为 Reconciliation 的 diff 算法。Reconciliation 算法通过递归地比较新旧虚拟 DOM 树的每个节点,找出节点的差异,并将这些差异应用到实际的 DOM 上。整个过程是递归的&#x…...

综合知识篇07-软件架构设计考点(2024年软考高级系统架构设计师冲刺知识点总结系列文章)
专栏系列文章: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html案例分析篇00-【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例…...

【GPT-SOVITS-05】SOVITS 模块-残差量化解析
说明:该系列文章从本人知乎账号迁入,主要原因是知乎图片附件过于模糊。 知乎专栏地址: 语音生成专栏 系列文章地址: 【GPT-SOVITS-01】源码梳理 【GPT-SOVITS-02】GPT模块解析 【GPT-SOVITS-03】SOVITS 模块-生成模型解析 【G…...

Flutter第四弹:Flutter图形渲染性能
目标: 1)Flutter图形渲染性能能够媲美原生? 2)Flutter性能优于React Native? 一、Flutter图形渲染原理 1.1 Flutter图形渲染原理 Flutter直接调用Skia。 Flutter不使用WebView,也不使用操作系统的原生控件,而是…...

[氮化镓]GaN中质子反冲离子的LET和射程特性
这篇文件是一篇关于氮化镓(GaN)中质子反冲离子的线性能量转移(LET)和射程特性的研究论文,发表在《IEEE Transactions on Nuclear Science》2021年5月的期刊上。论文的主要内容包括: 研究背景:氮…...

【项目】C++ 基于多设计模式下的同步异步日志系统
前言 一般而言,业务的服务都是周而复始的运行,当程序出现某些问题时,程序员要能够进行快速的修复,而修复的前提是要能够先定位问题。 因此为了能够更快的定位问题,我们可以在程序运行过程中记录一些日志,通…...

安卓国产百度网盘与国外云盘软件onedrive对比
我更愿意使用国外软件公司的产品,而不是使用国内百度等制作的流氓软件。使用这些国产软件让我不放心,他们占用我的设备大量空间,在我的设备上推送运行各种无用的垃圾功能。瞒着我,做一些我不知道的事情。 百度网盘安装包大小&…...

健身·健康行业Web3新尝试:MATCHI
随着区块链技术进入主流,web3 运动已经开始彻底改变互联网,改写从游戏到金融再到艺术的行业规则。现在,MATCHI的使命是颠覆健身行业。 MATCHI是全球首个基于Web3的在线舞蹈健身游戏和全球首个Web3舞蹈游戏的发起者,注册于新加坡&a…...

VB.NET高级面试题:什么是 VB.NET?与 Visual Basic 6.0 相比有哪些主要区别?
什么是 VB.NET?与 Visual Basic 6.0 相比有哪些主要区别? VB.NET是一种面向对象的编程语言,是微软公司推出的.NET平台上的一种编程语言,用于构建Windows应用程序、Web应用程序和Web服务等。它是Visual Basic的后续版本࿰…...

30.HarmonyOS App(JAVA)鸿蒙系统app多线程任务分发器
HarmonyOS App(JAVA)多线程任务分发器 打印时间,记录到编辑框textfield信息显示 同步分发,异步分发,异步延迟分发,分组任务分发,屏蔽任务分发,多次任务分发 参考代码注释 场景介绍 如果应用的业务逻辑比…...

伺服电机编码器的分辨率指得是什么?
伺服电机编码器的分辨率是伺服电机编码器的重要参数。 一般来说,具体的伺服电机编码器型号可以找到对应的分辨率值。 伺服电机编码器的分辨率和精度不同,但也有一定的关系。 伺服电机编码器的分辨率是多少? 1、伺服编码器(同步伺…...

WPF中使用LiveCharts绘制散点图
一、背景 这里的代码使用MVVM模式进行编写 二、Model public class DataPoint{public double X { get; set; }public double Y { get; set; }} 三、ViewModel public class ScatterChartViewModel{public SeriesCollection Series { get; set; }public ScatterChartViewMod…...

Android Studio实现内容丰富的安卓博客发布平台
获取源码请点击文章末尾QQ名片联系,源码不免费,尊重创作,尊重劳动 项目编号078 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端: 1.注册登录 2.查看博客列表 3.查看博客详情 4.评论博客, 5.…...

【GPT-SOVITS-01】源码梳理
说明:该系列文章从本人知乎账号迁入,主要原因是知乎图片附件过于模糊。 知乎专栏地址: 语音生成专栏 系列文章地址: 【GPT-SOVITS-01】源码梳理 【GPT-SOVITS-02】GPT模块解析 【GPT-SOVITS-03】SOVITS 模块-生成模型解析 【G…...

数据结构大合集02——线性表的相关函数运算算法
函数运算算法合集02 顺序表的结构体顺序表的基本运算的实现1. 建立顺序表2. 顺序表的基本运算2.1 初始化线性表2. 2 销毁顺序表2.3 判断顺序表是否为空表2.4 求顺序表的长度2.5 输出顺序表2.6 按序号求顺序表中的元素2.7 按元素值查找2.8 插入数据元素2.9 删除数据元素 单链表的…...

threejs案例,与静态三角形网格的基本碰撞, 鼠标环顾四周并投球游戏
创建一个时钟对象: const clock new THREE.Clock();这行代码创建了一个新的THREE.Clock对象,它用于跟踪经过的时间。这在动画和物理模拟中很有用。 2. 创建场景: const scene new THREE.Scene();这行代码创建了一个新的3D场景。所有的物体(如模型、灯…...

将FastSAM中的TextPrompt迁移到MobileSAM中
本博文简单介绍了SAM、FastSAM与MobileSAM,主要关注于TextPrompt功能的使用。从性能上看MobileSAM是最实用的,但其没有提供TextPrompt功能,故而参考FastSAM中的实现,在MobileSAM中嵌入TextPrompt类。并将TextPrompt能力嵌入到MobileSAM官方项目提供的gradio.py部署代码中,…...

KY191 矩阵幂(用Java实现)
描述 给定一个n*n的矩阵,求该矩阵的k次幂,即P^k。 输入描述: 第一行:两个整数n(2<n<10)、k(1<k<5),两个数字之间用一个空格隔开,含义如上所示…...

基于Python的股票市场分析:趋势预测与策略制定
一、引言 股票市场作为投资领域的重要组成部分,其价格波动和趋势变化一直是投资者关注的焦点。准确预测股票市场的趋势对于制定有效的投资策略至关重要。本文将使用Python编程语言,结合时间序列分析和机器学习算法,对股票市场的历史数据进行…...

【C++】了解一下编码
个人主页 : zxctscl 如有转载请先通知 文章目录 1. 前言2. ASCII编码3. unicode4. GBK5. 类型转换 1. 前言 看到string里面还有Template instantiations: string其实是basic_string<char>,它还是一个模板。 再看看wstring࿱…...

生成式人工智能在金融领域:FinGPT、BloombergGPT及其未来
生成式人工智能在金融领域的应用:FinGPT、BloombergGPT 及其他 引言 生成式人工智能(Generative AI)是指能够生成与输入数据相似的新数据样本的模型。ChatGPT 的成功为各行各业带来了许多机会,激励企业设计自己的大型语言模型。…...

webpack5零基础入门-10babel的使用
Babel JavaScript 编译器。 主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中 1.安装相关包 npm install -D babel-loader babel/core babel/preset-env 2.进行相关配置 2.1第一种写法是在webp…...

SAR ADC教程系列5——FFT频谱泄露以及相干采样
频谱泄露的出现以及如何规避? 为什么要相干采样? 1.分析ADC输出信号的频谱工具:DFT(Discrete Fourier Transform) 重点:DFT相邻频谱频率间隔为fs/N 如何规避频谱泄露? 对于DFT,它对于接收到的信…...

算法D48 | 动态规划10 | 121. 买卖股票的最佳时机 122.买卖股票的最佳时机II
股票问题是一个动态规划的系列问题,今日安排的题目不多,大家可以慢慢消化。 121. 买卖股票的最佳时机 视频讲解:https://www.bilibili.com/video/BV1Xe4y1u77q https://programmercarl.com/0121.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A…...

Windows10安装RubyRails步骤
2024年3月14日安装,亲测。记录一下以便后续需要查看。 首先在官网下载RubyInstaller for Windows - 国内镜像 rubyinstaller.cn 版本是3.3.0 下载完后图形化界面安装 安装完毕,出现Ruby的命令行,或者在开始菜单出现start command prompt wi…...

Sqlserver 模糊查询中文及在mybatis xml【非中文不匹配查询】N@P2问题
问题 sqlserver模糊查询或相等,两者都无法查询。 百度方案解释 Like 后的N是表示unicode字符。获取SQL Server数据库中Unicode类型的数据时,字符串常量必须以大写字母 N 开头,否则字符串将转换为数据库的默认代码页(字符集编码)࿰…...

旧华硕电脑开机非常慢 电脑开机黑屏很久才显示品牌logo导致整体开机速度非常的慢怎么办
前提条件 电池需要20%(就是电池没有报废)且电脑接好电源,千万别断电,电脑会变成砖头的 解决办法 更新bios即可解决,去对应品牌官网下载最新的bios版本就行了 网上都是一些更新驱动啊...

【go语言开发】性能分析工具pprof使用
本文主要介绍如何在项目中使用pprof工具。首先简要介绍pprof工具的作用;然后介绍pprof的应用场景,主要分为工具型应用和服务型应用。最后数据分析项目,先采集项目信息,再可视化查看 文章目录 前言应用场景工具型应用服务型应用 数…...