跨平台框架Flutter工作原理初探

前言

Flutter是开发跨平台应用的框架,支持将应用打包到几乎市面所有平台,本文较浅层次探究flutter框架的工作原理

参考来源为flutter中文社区官方文档

Flutter 开发文档 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter

flutter的布局

组合性

widget是组合其他简单而基础的widget的方式构建的,这也是flutter官方编写官方widget的理念,一个很鲜明的例子就是padding是widget而不是widget属性

RenderObjectWidget

这是widget递归构建的底层,用于在渲染树(存储用户界面几何信息的数据结构)构建子节点,flutter开发者无需创建这些对象,而是使用widget来操纵渲染树

保持widget渲染高性能的关键

次线性布局

Flutter对每一帧执行一次布局操作,约束信息通过父节点调用子节点布局方法向下传递,子节点递归执行自己的布局操作,并将几何信息返回添加到渲染树

一旦渲染对象从布局中返回,该对象将不会被再次访问,直到下一帧布局

布局期间,从父节点流向子节点的唯一信息是约束信息,从子节点流向父节点的唯一信息是几何信息

  • 每个 Widget 接收来自其父 Widget 的约束(如最大/最小宽度和高度),然后确定自己的大小。
  • 父 Widget 会根据子 Widget 的大小和其他因素(如布局规则)来决定子 Widget 的位置。
  • 如果子 Widget 在连续的布局过程中接收到相同的约束,并且没有标记为需要重建(脏),则可以快速完成布局,无需重新计算。
  • 父 Widget 可以根据子 Widget 的大小信息进行布局,但在某些情况下,即使子 Widget 的大小发生变化,父 Widget 也不需要重新布局。
  • 在某些情况下,如果父 Widget 对子 Widget 施加了严格的约束,子 Widget 的大小变化不会迫使父 Widget 重新布局。

次线性widget构建

Widget、Element 和 State

        Widget:是不可变的,定义了 UI 的结构和配置

        Element:是 Widget 的实例化,形成了一个树结构(Element 树),用来管理 Widget 的布局和状态。它们是可变的,并能够记住 Widget 的父子关系

        State:与 Stateful Widgets 相关联的对象,用于保存可变数据

次线性 Widget 构建

        当状态改变,相关的 Element 会被标记为 "脏"(需要重新构建)

        Flutter 维护了一个脏 Element 的列表。在构建过程中,只有标记为脏的 Element 会被重新构建,而不是整个树

单向数据流和清洗机制

        数据在 Element 树中单向向下传递,每个 Element 在一个构建周期中最多被访问一次

        一旦 Element 被更新(清洗),在当前构建周期内它不会再被标记为脏,因为它和它的所有祖先都已经是最新的

Widget 的不可变性和重用

        由于 Widgets 是不可变的,如果父 Widget 重建了,但相关的 Element 没有变脏,则该 Element 可以直接重用,无需重新构建

        Element 可以通过比较 Widget 的身份(而非其属性)来快速检查是否需要更新

InheritedWidgets 的使用

        为了避免在构建过程中频繁遍历父链(例如,查找主题颜色等),Flutter 使用 InheritedWidgets在 Element 上维护一个哈希表来高效地向下传递信息,避免了深度遍历的高成本

线性协调

  • Flutter 不使用传统的树差异比较算法,而是通过一个 O(N) 算法来独立检查每个 element 的子节点,以确定是否可以重用该 element
  • 子列表协调算法优化了几种情况:空的旧子列表、完全相同的新旧列表、列表中某位置的插入或删除操作,以及含有相同 key 的 widget 的识别

树结构优化

  • Element 的重用对性能至关重要,因为 element 保存着 Stateful widget 的状态对象和底层的渲染对象
  • 全局树更新(通过 GlobalKey 实现)允许将 widget 在 element 树中移动而不重新构建它们,从而保留状态和布局信息
  • 当 element 被重用时,其相关的渲染对象可以保留布局信息,减少了不必要的布局计算

恒定因子优化

  • Flutter 的渲染树不依赖于具体的子模型,这提高了布局方法的效率
  • 视觉渲染树和 widget 的逻辑树是分开的,以提高布局和绘制计算的效率
  • 文本由专门的渲染对象(RenderParagraph)处理,避免了文本布局的重复计算
  • Flutter 使用观察者模式,其中可观察对象(如 Animation)在值变化时通知观察者,允许渲染树仅在必要时进行重绘,而不是完全重建和重绘

Element 树和 RenderObject 树的分离

  • Flutter 中的 RenderObject 树(负责渲染)和 Element 树(基于 Widget 的逻辑结构)是分开的,尽管它们在结构上有所同构
  • 这种分离带来了多个好处,包括性能优化(只遍历布局相关的树)、清晰的 API 设计(分离职责),以及类型安全(运行时确保子节点类型的合适性)

无限滚动

  • Flutter 支持无限滚动列表,这是通过构造器模式实现的,其中 ListView 按需构建 widget

视窗感知布局

  • 可滚动的 widget 由一个外部的 Viewport 组成,它定义了一个比实际屏幕更大的内部空间
  • Viewport 的子节点不是普通的 RenderBox,而是实现了视窗感知协议的 RenderSliver
  • Sliver 布局协议中的约束和几何数据结构与传统的盒子布局不同,它们更关注于视窗口内的可见空间和滚动效果

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

防御保护--第一次实验

目录 一,vlan的划分及在防火墙上创建单臂路由 二,创建安全区域 三,配置安全策略 四,配置认证策略 五,配置NAT策略 1.将内网中各个接口能够ping通自己的网关 2..生产区在工作时间内可以访问服务器区,仅…

vivado 2018.3 烧写固化FPGA verilog代码以及出现的问题解决

vivado一般是与SDK同时使用的,像zynq系列,通过SDK烧写固化代码很方便,但是有的时候比如本人目前使用的是XC7K325T FPGA进行的开发,不会用到SDK软件,所以烧写固化代码想通过vivado直接操作。 1、按照网上百度的方法进行设置,如下 遇到的第一个问题就是在vivado2018.3的fl…

Blender教程(基础)-物体添加-03

1、打开的界面如下图会存在3个物体、英文状态下按键盘字母A全选、然后按键盘delete删除。 删除后一片空白 2、新增物体 方式1:在英文状态下按键盘shiftA组合键弹出如下添加物体弹窗 方式2:在菜单下找到添加点击弹出添加选项 3、举例新增物体 采用上述…

【数字通信】数字带通传输

数字调制和数字带通传输系统 数字调制解调 数字调制 用数字基带信号控制载波,把数字基带信号变换为数字带通信号的过程 目的:数字基带信号含大量低频分量,无法通过具有带通特性的信道传输。需对数字基带信号进行数字调制使信号与信道的特…

log4j2 java api 入门介绍

概述 Log4j 2 API 提供了应用程序应该编码的接口,并提供了实现者创建日志实现所需的适配器组件。 虽然 Log4j 2 在 API 和实现之间被分解,但这样做的主要目的不是允许多个实现,尽管这当然是可能的,而是明确定义在“正常”应用程…

YOLOv8融合改进 更换检测头同时改进C2f模块

一、Detect_DyHead检测头和C2f-EMSC,C2f-EMSCP模块 详细介绍和代码在往期的博客里: Detect_DyHead: (YOLOv8改进检测头Detect为Detect_Dyhead-CSDN博客) C2f-EMSC和C2f-EMSCP: (YOLOv8改进之多尺度转换模块C2f-EMSC和C2f-EMSCP-CSDN博客) 二、算法实现 1、将检测…

github连不上

github连不上 错误提示解决方案 错误提示 fatal: unable to access ‘https://github.com/Ada-design/qianduan.git/’: Failed to connect to github.com port 443 after 21073 ms: Couldn’t connect to server 解决方案 下载steam https://steampp.net/ 安装成功之后&am…

Linux系统明明还有足够的物理内存,调用fork却返回ENOMEM

使用systemtab hook fork,定位到报错调用路径SYSCALL_DEFINE0(fork)-》kernel_clone-》copy_process-》copy_mm-》dup_mm-》dup_mmap-》security_vm_enough_memory_mm-》__vm_enough_memory __vm_enough_memory返回了 -ENOMEM。其源码如下: 从代码可知f…

算法38:子数组的最小值之和(力扣907题)----单调栈

题目: 给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。 示例 1: 输入:arr [3,1,2,4] 输出:17 解释: 子数组为 [3],[…

Java集合总览

1.总览 Java中的集合分List、Set、Queue、Map 4种类型。 List:大多数实现元素可以为null,可重复,底层是数组或链表的结构,支持动态扩容 Set:大多数实现元素可以为null但只能是1个,不能重复, …

MySQL 聚集与非聚集索引

文章目录 1.聚集索引1.1 介绍1.2 优点1.3 缺点 2.非聚集索引3.区别参考文献 MySQL 中,根据索引树叶结点存放数据行还是数据行的地址,可以将索引分为两类: 存放数据行:聚集索引存放数据行地址:非聚集索引 InnoDB 使用聚…

Linux学习之文件系统与动静态库

目录 一,文件的管理 什么是磁盘? 磁盘的逻辑抽象结构 格式化 inode 挂载 软硬链接 二,动静态库 什么是动静态库? 1.站在库的制作者角度 静态库: 制作一个静态库 2.站在静态库使用者的角度 动态库 作为制…

windows安装PostgreSQL后进行远程连接,发生SSL错误

1. 报错情况 SSL 关闭 的 pg_hba.conf 记录 (pgjdbc: autodetected server-encoding to be GB2312, if the message is not readable, please check database logs and/or host, port, dbname, user, password, pg_hba.conf) 或是乱码提示,提示中有SSL、 pg_hba.con…

C语言KR圣经笔记 5.12 复杂声明

5.12 复杂声明 C 语言有时会因为声明的语法而受到谴责,特别是涉及函数指针的声明语法。语法试图使声明和使用一致;在简单的情况下它的效果不错,但在更复杂的情况下会让人困惑,因为声明不能从左往右读,而且括号被过度使…

RabbitMQ快速上手

首先他的需求实在什么地方。我美哟明显的感受到。 它给我的最大感受就是脱裤子放屁——多此一举,的感觉。 他将信息发送给服务端中间件。在由MQ服务器发送消息。 服务器会监听消息。 但是它不仅仅局限于削峰填谷和稳定发送信息的功能,它还有其他重要…

Nacos(先解释专属名词,然后大白话讲解+安装配置教程+代码实例 信我,看了必会!!点进来吧各位大佬们)

Nacos 先来一个注意:以下涉及到配置和项目的创建,我的jdk是jdk17,idea是2023.2.4,并且是社区版的idea 1.什么是Nacos Nacos是Dyamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态…

重生奇迹MU平民玩家推荐的职业

女魔法师 女魔法师是一个非常适合平民玩家的职业选择。她拥有着强大的魔法攻击能力,可以轻松地击败敌人。而且女魔法师的装备价格相对较低,适合玩家们的经济实力。 精灵射手 精灵射手是一个非常灵活的职业选择。他们可以远程攻击,可以在战…

数据结构之生成树及最小生成树

数据结构之生成树及最小生成树 1、生成树概念2、最小生成树 数据结构是程序设计的重要基础,它所讨论的内容和技术对从事软件项目的开发有重要作用。学习数据结构要达到的目标是学会从问题出发,分析和研究计算机加工的数据的特性,以便为应用所…

centos7 挂载windows共享文件夹报错提示写保护

centos7挂载windows共享时,提示被共享的位置写保护,只能以只读方式挂载,紧接着就是以只读方式挂载失败 原因是组件少装了 yum install cifs-utils 安装完后,正常挂载使用。 下载离线安装包 下载离线包下载工具 下载离线安装包…

神经网络:表述(Neural Networks: Representation)

1.非线性假设 无论是线性回归还是逻辑回归,当特征太多时,计算的负荷会非常大。 案例: 假设我们有非常多的特征,例如大于 100 个变量,我们希望用这 100 个特征来构建一个非线性的多项式模型,结果将是数量非…