Flutter:架构概览

news2024/10/6 5:59:08

概览

Flutter本质上是一个跨平台的UI工具集,允许在各自操作系统上复用同样的代码。
尽可能提供原生体验的高性能和复用代码。

开发中,Flutter应用在一个VM上运行,使得可在保留状态且无需重新编译情况下,进行热加载。
发行时,Flutter应用会直接通过AOT编译为机器码或者是JS。

分层模型

Flutter是一个可拓展的分层系统,可被视为各个独立组件的集合,上层组件依赖下层,上层无法越界访问更下层的组件,框架内各部分是可选可替代的。

分为框架、引擎、嵌入层
在这里插入图片描述

嵌入层

对于底层操作系统,Flutter应用程序的包装方式与其他原生应用相同,每个平台都会包含一个特定的嵌入层,提供一个程序入口,使得程序可以与底层操作系统进行协调、访问服务和管理事件循环队列。
对于不同平台,嵌入层使用的语言都不一样。Flutter代码可以作为模块集成到现有应用或作为应用主体。

引擎

主要使用C++编写,提供Flutter应用所需原语。
当需要绘制新一帧内容时,引擎将负责对需要合成的场景进行栅格化。
其提供Flutter核心API的底层实现:图形、文本布局等…

引擎将底层C++代码包装成Dart代码,通过dart:ui暴露给Flutter框架层。该库暴露了最底层的原语,包括用于驱动输入,图形等子系统的类

框架

开发者通过Flutter框架和Flutter交互,该框架提供了以Dart语言编写的现代响应式框架。
自下而上有:

Foundational and Annimation、Painting、Gestures

Foundational:基础类
Annimation:动画
Painting:绘画
Gestures:手势
向上层提供常用的抽象

渲染层

提供操作布局的抽象,操作层使得可以构建一颗可渲染对象的树,可动态更新。

Widget

组合的抽象,每个渲染层中的渲染对象在widget层中有一个对应的类。
widget层可让你自由组合需要复用的各种类,引入了响应式编程模型。

Material和Cupertino

提供了全面的widget层的原语组合,分别实现了Material和IOS设计规范。

其他更高层级的功能被拆分到不同的软件包中。

应用剖析在这里插入图片描述

  • Dart应用:将Widget合成预期的UI,实现业务。
  • 框架:提供API封装,将应用widget树构建在一个Scene中。
  • 引擎:将合成的Scene进行栅格化、封装Flutter进行封装,暴露功能给dart:ui API给框架、使用嵌入层API与平台进行整合。
  • 嵌入层:协调底层操作系统的服务、管理事件循环体系、暴露特定平台API给应用集成嵌入层。
  • 运行器:将嵌入层暴露的平台API合成为目标平台可运行的应用包。

响应式用户界面

Flutter是一个响应式的且伪声明式的UI框架,
随widget构造方法引入的新输入会随着其build方法传播给更低等级的widget;
而底层的widget中出现的修改也会沿着结构树通过event handler向上传播。
函数-响应式、指令-响应式都有出现,
前者是指widget的build方法中只包含其针对变化如何响应的表达式,
后者则包含一系列构造子元素的表达式,用于描述该widget如何响应变化。

Flutter,widget用来配置对象树的不可变类,这些widget管理单独的布局对象树,接着参与管理合成的布局对象树。

Flutter核心是一套高效的遍历树的变动的机制,将对象树转换为更底层的对象树,在树间传递更改。

build将状态转换为UI,在框架需要都可以被调用,可快速执行且没有额外影响,依赖DART的运行时特征:对象的快速实例化和清除。

Widgets

Flutter强调以widgets为组成单位。widgets是构建flutter应用界面的基础块,每个widget都是一部分不可变的UI声明。

widget通过布局组合形成一种层次结构关系,每个widget都嵌套在其父级的内部,可以通过父级接收上下文。从根布局(MaterialApp或CupertinoApp)开始,自上而下。

应用根据事件交互,通知框架替换层级中的旧widget为新的widget,比较新旧widget,高效更新。
Flutter拥有自己的UI控制实现,不使用系统自带。
这样提供了无限拓展性,不受系统提供的拓展限制。
Flutter可直接合成所有的场景,避免与原生平台来回切换,避免了性能瓶颈。
将应用的行为与操作系统的依赖解耦,实现不同平台,体验一致。

组成

widget通常由更小的且用途单一的widget组合而成,提供更强大的功能。
Flutter 在widget层中使用了widget来表示屏幕上的绘制、布局等
Flutter 在动画层,Animation和Tween涵盖了大部分的设计空间
Flutter 在渲染层,RenderObject用来描述布局、绘制、触摸判断等
Widget思想是 浅而广,最大限度地增加可能的组合数量,每个widget完成一件事,将核心功能抽象,如边距等基础功能,被实现为单独的组件

构建widget

build方法会返回一个新的元素树,这棵树更具体地表示了widget在ui中的部分。
框架会递归请求每个widget进行构建,直到整棵树都被具体的可渲染对象描述为止。
框架会将可渲染的对象缝合在一起,组合成可渲染对象树。

每个渲染帧,Flutter都可以根据变化的状态,调用build方法重建部分UI。
因此,build方法轻量且能快速返回widget,计算工作通过一些异步方法完成,并存储在状态中,由build使用。

widget状态

框架包含两种核心的widget:有无状态widget StatefulWidget / StatelessWidget
改变state时,调用setState来告知框架,调用State的构建方法来更新UI

Flutter将状态和widget对象分离,无需担心状态丢失,可随时创建新实例和复用已存在的状态对象

状态管理

通过context传递状态信息,子widget通过build(BuildContext context)方法接受父widget传入的信息,初始化所需数据。

随着widget树层级加深,依赖树形结构上下传递状态信息会变得十分困难。
InheritedWidget将一个共同的祖先结点包裹在widget树中
在这里插入图片描述

final studentState = StudentState.of(context);

通过of(context)会根据当前构建的上下文,返回类型为StudentState的在树中距离最近的祖先结点。
InheritedWidget包含updateShouldNotify()来判断widget是否需要重建。

provider用于状态管理,对InheritedWidget进行进一步报装,如flutter_hooks也可以用来替换状态至ui。

渲染过程

Flutter的渲染模型

Android系统提供了将自身绘制到Canvas对象的组件,接着使用C/C++编写的Skia图像引擎,调用CPU和GPU完成再设别上绘制。
一般的跨平台框架会在Android和IOS的UI底层库上创建一层抽象,程序代码通常使用JS进行编写,基于与系统进行交互来显示UI界面,当UI和应用逻辑有繁杂的交互时更会如此。

Flutter通过绕过系统UI组件库,使用自己的widget内容集,削减了抽象层的开销。
绘制Flutter图像内容的Dart代码被编译为机械码,使用平台提供的skia渲染,Flutter也嵌入自己的skia副本。

输入事件执行流程

  • User input 响应用户输入:对输入手势进行响应(点击效果等)
  • Animation 执行动画:由计时器触发界面更改
  • Build 构建组件:创建widget在屏幕上
  • Layout 组件布局:定位和测量屏幕上的元素 -----------------
  • Paint 绘画组件:将元素转换为虚拟表示 ----------------- Rendering渲染
  • Composition 整合组件:按绘画顺序覆盖组件 -----------------
  • Rasterize 光栅化:将输出翻译为GPU绘画指令

Widget到Element

build方法返回一棵基于当前应用状态来绘制UI的widget子树。
build方法会在必要时,根据状态引入新widget,如color为空时引入ColoredBox,image引入RawImage,Text引入RichText

构建时,Flutter会将widget转换为Element树,每个widget都有一个对应的Element
分为两种:
ComponentElement:其他Element的宿主
RenderObjectElement:参与布局或者绘制阶段的Element
在这里插入图片描述
RenderObjectElement 是底层 RenderObject 与对应的 widget 之间的桥梁。

对 widget 树做的任何操作(例如将 Text(‘A’) 替换成 Text(‘B’))都会返回一个新的 widget 对象集合。但这并不意味着底层呈现的内容必须要重新构建。 Element 树每一帧之间都是持久化的,因此起着至关重要的性能作用, Flutter 依靠该优势,实现了一种好似 widget 树被完全抛弃,而缓存了底层表示的机制。 Flutter 可以根据发生变化的 widget,来重建需要重新配置的 Element 树的部分。

布局和渲染

在渲染树中,每个节点的基类都是RenderObject,为布局和绘制定义了一个抽象模型。
每个RenderObject都了解其父节点的信息,但对于其子节点,除了访问和获得他们的布局约束,并没有更多的信息。

这样使得RenderObject拥有更高效的抽象能力。

构建时,Flutter会为Element树中的每个RenderObjectElement创建或更新其对应的一个从RenderObject对象。

在这里插入图片描述
大部分Flutter widget 由一个继承了RenderBox的子类的对象渲染的,其呈现出的RenderObject拥有固定的大小。提供了盒子限制模型,为每个widget关联了渲染的最小和最大的宽度和高度。

进行布局时,Flutter会以DFS遍历渲染树,将限制以自上而下的方式从父节点传递给子节点。
子节点若要确定自己的大小,必须循环父节点传递的限制。
子节点的响应方式是在父节点建立的约束内将大小以自下而上的方式传递给父节点。

遍历完一次树后,每个对象都通过父级约束而拥有了明确的大小,随时可以通过调用paint渲染。

盒子限制模型的对象布局的时间复杂度为O(n)
父节点可通过设定最大和最小的尺寸限制,决定其子节点对象的大小。
父节点可以决定子节点的宽度,然后自适应布局高度。

LayoutBuilder widget 的子节点可以得到从上层传递下来的约束,并合理利用该约束对象。

RenderObject根节点为RenderView,代表渲染树的总体输出。当平台需要渲染新一帧内容时,会调用一次compositeFrame方法,是RenderView的一部分。

compositeFrame创建一个SceneBuilder来触发当前画面的更新,更新完后,RenderView会将合成的画面传递给dart:ui中的Window.render方法来控制GPU进行渲染。

平台嵌入层

Flutter界面构建、布局、合成和绘制都由Flutter自己完成,获取纹理和联动应用底层的生命周期的方法,不可避免地根据平台特性而改变。Flutter引擎本身是平台无关,提供ABI接口设置并使用Flutter。

平台嵌入层提供一个入口,初始化Flutter引擎,获取UI和栅格化线程。嵌入层充当宿主操作系统和Flutter之间的粘合剂。还负责管理应用的声明周期。

Flutter集成其他代码

Flutter提供了多种代码交互机制,可以将原生代码嵌入Flutter,或者Flutter嵌入现有应用。

平台通道

Flutter通过 平台通道 调用自定义代码。通过创建一个常用的通道,开发者可以在Dart与使用Kotlin等语言编写的平台组件间发送和接收消息。

数据由Dart类型序列化为一种标准格式,再反序列化为kotlin等中的等效类型。
在这里插入图片描述

Web支持

。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/740745.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【教程】Unity 联动 MSMQ 消息通讯

开发平台:Unity 2021.3.7 通讯平台:Windows 10 依赖DLL:System.Messaging.dll   一、本文目标 了解与操作 Windows 平台上建立 Unity 与 MSMQ 通讯机制。实现基础的通讯功能。   二、准备:启用 MSMQ 服务项 注意:默…

操作符——区别C++前置++和后置++

这里写目录标题 1.问题引出Q:重载或者--的时候如何区分前置和后置? 2.C规范3.前后置实现4.为什么i;可以 i;不行 1.问题引出 Q:重载或者–的时候如何区分前置和后置? 以前C对前置和后置没有很好的办法可以区分,为了解决这个问题&…

面试之SpringAOP的理解:

AOP(面向切面编程)指的是那些业务本身无关,但是被业务模块所共同调用的业务逻辑或责任(日志管理,权限管理等)封装起来,便于减少系统的重复代码,降低系统见的耦合性,有利于未来系统的扩展性。 S…

IOS开发工程师的发展前景怎么样

本文目录一览 1,iOS开发工程师就业前景怎么样2,北大青鸟java培训IOS开发前景怎么样3,iOS开发工程师就业前景怎么样4,作为一个iOS开发程序员我的未来何去何从5,IOS开发工程师的发展前景怎么样6,ios开发工程…

Ubuntu 20.04 L2TP VPN 自动重连脚本,cron定时任务设置

1、连接VNP脚本 reconnect_l2tp_vpn.sh #!/bin/sh ppp0_flagifconfig | grep ppp0 echo $ppp0_flag if [ -z "$ppp0_flag" ];thenecho "connet to vpn ..."# connet vpn# echo PASSWORD | sudo -S 这样可以不用手动输入密码!echo abc123| su…

我爱学QT-QT信号和槽

1.给控件改名字 为了分析代码方便,我们要给控件改名字。要通俗易懂。 2.信号和槽 信号:信号就是指控件发出的特定的信号。 比如按钮的信号 槽:槽就是槽函数的意思,我们可以把槽函数绑定在某一个控件的信号上。 3.怎么关联信号…

IntelliJ IDEA中生成jar包并运行

1. 过程 依次选择菜单:File->Project Structure…,打开“Project Structure”界面。 在打开界面的左侧列表中选择:Artifacts,点击右侧出现的号。 在出现的菜单中依次选择:JAR->From modules with dependencies…

家政行业丨制作便捷高效的家政小程序

随着现代生活节奏的加快和家庭需求的多样化,越来越多的人开始寻找一种更方便、更高效的方式来获取家政服务。而家政小程序的兴起为这一需求提供了理想的解决方案。本文将简要介绍家政小程序是什么,探讨家政小程序的好处,并提供一些制作搭建家…

element上传文件对格式限制的处理

需求&#xff1a;上传的文件格式必须是pdf格式&#xff0c;方便查看 规定多种格式用逗号隔开 使用这个属性可以规定上传文件格式&#xff0c;但是有bug 可以手动改变显示的文件类型&#xff0c;还是可以传其他文件类型 所以需要在上传的时候限制上传的文件格式 上传组件 <…

X2000 Linux 调试VL53L4CD

由于VL53L4CD具有更高的精度&#xff0c;更低的功耗&#xff0c;所以尝试将VL53L4CD移植到X2000上进行测试。 一、下载驱动 en.VL53L4CD_LinuxDriver 二、SDK中加入驱动 1、加入源码 在\module_driver\devices下创建VL53L4CD文件夹&#xff0c;再将\en.VL53L4CD_LinuxDriver…

网络爬虫-jd滑块验证码

仅供研究学习使用。 目标站点 --> 京东网页登录 当我们输入账号密码后&#xff0c;点击登录&#xff0c;首先映入眼帘的是一个滑块&#xff0c;那我们先分析一下滑块吧。 上图是滑块的有关信息&#xff0c;左边的横线是请求的url&#xff0c;右边是参数&#xff0c;很显然&…

敏捷测试自动化

目录 前言&#xff1a; 敏捷宣言 敏捷软件开发VS传统方法 敏捷云服务 对什么进行自动化&#xff1f; 测试自动化的技巧 关于敏捷测试和自动化测试的关键信息 前言&#xff1a; 敏捷测试自动化是在敏捷开发环境中使用自动化工具和技术来支持测试活动的一种方法。它旨在提…

SQL使用(一):如何使用SQL语句去查询第二高的值

今天刷MYSQL题的时候刷到这样一个题&#xff1a; 编写一个 SQL 查询&#xff0c;获取 Employee 表中第二高的薪水&#xff08;Salary&#xff09; 。------------| Id | Salary |------------| 1 | 100 || 2 | 200 || 3 | 300 |------------例如上述 Employee 表&a…

时间序列预测 | Matlab自回归差分移动平均模型ARIMA时间序列预测,可实现多步预测,对未来的数据实现预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 时间序列预测 | Matlab自回归差分移动平均模型ARIMA时间序列预测,可实现多步预测,对未来的数据实现预测 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源码 %% …

C语言比较容易出错的printf语句/cout语句

请问以下代码的输出结果是什么&#xff1f; int main() {int n 2;//cout << n << n << n--;printf("%d %d %d", n, n, n--);system("pause");return 0; } 结果&#xff1a; 很奇怪&#xff1f; 为什么会这样&#xff1f; 原来自己之…

MOVEit再现新漏洞,多个版本受影响

今年6月&#xff0c;文件共享工具MOVEit Transfer曾曝出SQL 注入漏洞&#xff0c;能让远程攻击者访问其数据库并执行任意代码。最近&#xff0c;MOVEit Transfer 母公司Progress Software又披露了三个新漏洞。 这三个漏洞分别是 CVE-2023-36932、CVE-2023-36933 和 CVE-2023-36…

【ACL 2023】具有高效推理速度的中文领域文图生成扩散模型和工具链

近日&#xff0c;阿里云机器学习平台PAI与华南理工大学合作&#xff08;阿里云与华南理工大学联合培养项目&#xff09;在自然语言处理顶级会议ACL2023上发表了具有高效推理速度的中文领域文图生成扩散模型和工具链Rapid Diffusion。它是面向中文特定领域的文图生成模型&#x…

了解MQL4,轻松自定义外汇交易收益曲线

外汇交易是现代社会中增长最快的交易形式之一&#xff0c;而MQL4编程语言是一种针对外汇交易的编程语言。熟练使用MQL4编程语言可以帮助交易者轻松自定义外汇交易收益曲线。本文将介绍什么是MQL4&#xff0c;以及如何使用MQL4来自定义外汇交易收益曲线。 一、什么是MQL4 MQL4…

MyBatis 中的 SQL 映射文件如何配置参数映射,如何使用

MyBatis 中的 SQL 映射文件如何配置参数映射&#xff0c;如何使用 MyBatis 是一种开源的 Java 持久化框架&#xff0c;它可以自动将数据库中的数据映射到 Java 对象中&#xff0c;并且使得 Java 对象可以非常方便地存储到数据库中。在 MyBatis 中&#xff0c;SQL 映射文件是一…

Tomcat之安装与项目部署

Tomcat是一个免费、开源的javaWeb轻量级应用服务器 优于是使用Java开发的&#xff0c;需要运行在java虚拟机中&#xff0c;所以必须安装jdk&#xff0c;以提供运行环境。 Tomcat可以看做一个http服务器&#xff0c;通过组件Connector接收http请求并解析&#xff0c;然后把结果…