前言
作为一款跨平台移动应用开发框架,Flutter 确实在性能方面具有优势,这主要得益于它采用了自己的渲染引擎来完成 UI 渲染。Flutter 的渲染引擎使用 Skia 图形库直接将应用程序 UI 绘制到屏幕上,并且能够利用 GPU 加速来提高性能。
同时,Flutter 还采用了高效的图层树结构,可以快速计算和渲染复杂的 UI 元素,这也是 Flutter 在性能方面优于其他跨端框架的重要原因之一。
另外,Flutter 还具有热重载、自定义 UI 等优点,这些优势都使得 Flutter 成为了一个受欢迎的跨平台移动应用开发框架。
为了了解Flutter渲染优势,我们需要深入探究Flutter的渲染原理。本系列文章将采用通俗易懂的语言介绍Flutter的渲染原理,不仅能够帮助您了解Flutter的渲染优势,还能学习到前端通用的渲染原理。
导读
作为Flutter渲染原理的第一篇,本文不会深入分析Flutter的细节和源码,而是主要介绍Flutter UI框架到屏幕显示的整体流程,基于此流程结合生产消费者模型帮助读者建立一个完整的框架思维,主要内容如下:
-
第一章:Flutter渲染流程介绍。介绍Flutter渲染流程的基本概念和结构,为后续章节打下基础。
-
第二章:生产消费者模型。 讲解Flutter渲染基于生产消费者模型的原理和流程,帮助读者深入理解Flutter渲染的工作方式。介绍生产消费者模型中的加工厂和制造过程,阐述它在Flutter渲染框架中的重要作用。探究生产消费者模型中的消费者,揭示它在Flutter渲染框架中的作用和实现原理。
-
第三章:总结和展望。对前面章节进行总结,展望后续的本系列的更新计划。
目录
1.Flutter渲染流程介绍
下面是官方提供的Flutter框架图:
在Flutter框架图中,开发者与Framework层直接交互。这一层提供了UI框架,负责整个渲染流程。Engine层提供了Flutter的渲染引擎Skia,而Embedder层则是用于适配各个平台的基础层。然而,对于整个前端渲染框架来说,这些层次远远不够,无法触及操作系统和硬件层。如果有一个简单且完整的渲染框架流程图,应该是下面这个样子:
在App页面开发过程中,开发者编写UI代码并将其显示在屏幕上,这个过程可以概括为以下几个步骤:
- 开发者编写UI代码:开发者使用Flutter框架中的Widget编写应用程序的UI界面,包括布局、交互、逻辑等部分,这些代码最终会转换为UI渲染对象。
- Flutter UI框架:Flutter UI框架将开发者编写的UI代码转换为渲染对象,这些渲染对象RenderObject描述了要在屏幕上绘制的内容,组成了Flutter渲染树。
- Flutter渲染引擎:Flutter渲染引擎负责处理Flutter渲染树中的渲染对象,确定它们的绘制顺序、位置和透明度等属性。渲染引擎使用Skia绘图引擎将这些渲染对象转换为GPU可理解的图形数据。
- 操作系统:操作系统负责管理硬件和软件资源,为应用程序提供必要的环境和服务,包括内存管理、进程调度、输入输出等。操作系统还负责与GPU驱动程序交互,将渲染任务提交给GPU。
- GPU渲染:GPU通过硬件加速和优化等技术将图形数据转换为像素点,并对每个像素点进行处理和着色,以生成最终的图像数据。这个过程可以分为顶点处理、几何着色、裁剪、光栅化、像素着色等步骤,其中GPU使用并行计算的方式提高计算效率和图形处理的速度。
- 帧缓存:GPU将生成的像素点写入帧缓存中,帧缓存是一块内存区域,用于存储屏幕上每个像素点的颜色值。
- 屏幕显示:最后,操作系统将帧缓存中的像素点数据发送到GPU驱动程序,驱动程序再将数据传输给GPU,GPU再将数据发送到显示器上,显示器按照像素点的颜色值进行显示,将最终的图像呈现在屏幕上。
整个流程中,操作系统负责管理资源、提供必要的环境和服务,将渲染任务提交给GPU。Flutter UI框架和渲染引擎将开发者的UI代码转换为渲染对象,并进行处理和优化。GPU使用并行计算和硬件加速等技术对图形数据进行处理和渲染,最终将渲染结果输出到帧缓存中。最后,操作系统将帧缓存中的数据传输给GPU,GPU再将数据发送到显示器上,最终将渲染结果输出到屏幕上。
1.1 开发者编写的UI代码
开发者编写的代码是绝大部分是基于各技术栈的UI框架,常见的UI框架包括Android中的Android UI框架、iOS中的UIKit框架、React Native中的React框架以及Flutter中的Flutter框架等。
在Flutter中,面向开发者的UI核心是Widget。有一句广为人知的话是“万物皆可Widget”,这意味着在Flutter中,类似于Android中的Activity和iOS中的Controller等页面容器都可以使用Widget,而页面中的组件也同样适用Widget。而在Widget中的build方法返回的Widget组件便是UI框架需要的数据。
由开发者编写提供UI数据后,接下来轮到Flutter UI框架进行数据处理了。
1.2 Flutter UI框架
广义上的UI框架是什么?
广义上的UI框架是指提供一系列API和工具,帮助开发者构建用户界面的软件框架。这些框架通常提供了许多基本组件和功能,例如文本框、按钮、标签等,以及与用户交互的事件处理、布局和样式等。通过使用这些框架,开发者可以更轻松地创建各种应用程序,无需从头开始编写所有UI元素和逻辑。
广义上的UI框架不仅限于特定的操作系统或平台,也可以是跨平台的。例如,Flutter就是一个跨平台UI框架,可以在多个操作系统和设备上运行,如Android、iOS、Web、桌面应用等。而React Native也是一个跨平台UI框架,可以用于构建Android和iOS应用程序。
总之,广义上的UI框架是一种软件开发工具,使开发者能够更快速、高效地创建各种类型的用户界面。
Flutter UI框架又是什么?
Flutter的UI框架基于现代的响应式编程思想,使用一种名为Dart的编程语言编写。提供了许多基础组件和Widget,包括文本框、按钮、滑块、表格等,同时还有丰富的动画和效果组件。
Flutter还提供了强大的布局和样式系统,使开发者可以轻松构建美观、响应式的用户界面。
Flutter还支持热重载和快速开发周期,使开发者可以快速迭代和测试应用程序。总之,Flutter UI框架是一种现代、高效的工具,可以帮助开发者构建高质量的应用程序,并在多个平台上运行。
在Flutter UI框架中,当需要刷新UI时,它会获取开发者提供的Widget数据,将Widget树转换为渲染对象树,并将其交给渲染引擎处理。
1.3 Flutter渲染引擎
Flutter渲染引擎利用Skia图形引擎来实现跨平台的图形渲染。Skia是Google开发的跨平台2D图形引擎,它支持各种图形操作和效果,例如路径绘制、图像渲染、阴影、模糊等等,提供了丰富的API。
Flutter渲染树由多个RenderObject对象组成,每个RenderObject对象负责绘制一个小的图形元素,例如文本框、线条、按钮等等。Flutter框架自动构建和更新渲染树,开发者只需提供Widget树即可实现复杂的用户界面和动画效果。
Flutter渲染引擎负责处理Flutter渲染树中的渲染对象,确定它们的绘制顺序、位置和透明度等属性。使用Skia绘图引擎将这些渲染对象转换为GPU可理解的图形数据,以实现高性能的图形渲染和动画处理。
综上所述,Flutter渲染引擎是Flutter框架的核心之一,提供了高性能、可扩展、跨平台的图形渲染和动画处理能力,为开发者提供了极大的便利。
1.4 操作系统
在Flutter中,操作系统扮演了一个重要的角色,尤其是在渲染引擎和GPU渲染之间的交互中。
首先,Flutter的渲染引擎会生成一个绘图命令列表,包含所有需要在屏幕上渲染的UI元素,其中渲染引擎的渲染功能是基于操作系统或GPU提供的基础图形API来实现的。然后,这些绘图命令被发送到GPU进行实际的渲染操作。在此过程中,操作系统充当了中间人的角色,负责协调Flutter渲染引擎和GPU之间的交互。
具体来说,操作系统可以执行以下任务:
- 管理GPU资源:操作系统可以分配GPU资源,如内存和处理器时间,以确保Flutter应用程序可以在屏幕上流畅运行。
- 提供硬件加速:操作系统可以利用硬件加速技术,如OpenGL或Vulkan,来优化Flutter应用程序的渲染性能。
- 处理事件:操作系统可以处理屏幕上的用户事件,如触摸、点击等,并将这些事件传递给Flutter应用程序。
- 管理窗口:操作系统可以创建和管理应用程序窗口,并确保它们在屏幕上正确显示和渲染。
总之,操作系统在Flutter渲染引擎和GPU之间扮演了至关重要的角色,负责协调它们之间的交互,并确保Flutter应用程序在屏幕上正确显示和渲染。
Skia引擎生成的图形数据无法直接显示在屏幕上,需要通过GPU渲染。 GPU将对Skia引擎生成的图形数据进行处理和加工,以最终在屏幕上显示出来。
1.5 GPU渲染
GPU渲染部分就像是一个专门的艺术家,它会拿到由渲染引擎提供的绘图指令,然后将这些指令转化为屏幕上真正可见的图像。GPU渲染部分会负责处理颜色、阴影、反射等各种图形效果,并通过计算、填充、着色等操作,将绘图指令转化为最终的图像。
什么是硬件加速?
硬件加速实际就是把原本属于CPU做的计算工作交给GPU来处理,由于GPU具有高并发性和并行计算能力,因此GPU通常比CPU计算更快且更适合大量绘制对象或高分辨率的场景。不开启硬件加速时,Skia是配合CPU的计算能力进行软绘,GPU则主要执行后续的着色等流程,而开启硬件加速,SKia不仅可以利用GPU关于绘图方面的强大绘制能力,还可以实现更复杂的图形效果,如光照和阴影。
1.6 帧缓存
帧缓存是指一种用于存储渲染结果的内存缓存。在渲染过程中,GPU会将每一帧的渲染结果存储到帧缓存中,然后在下一帧的渲染开始前,将上一帧的渲染结果从帧缓存中读取出来,作为当前帧的背景。这样做可以使得UI的渲染更加流畅,因为GPU可以直接从帧缓存中读取上一帧的渲染结果,而无需重新计算整个场景。同时,帧缓存还可以用于实现一些特殊效果,例如流畅的动画效果和平滑的过渡效果等。
1.7 屏幕显示
讨论屏幕显示原理,我们首先需要了解屏幕是由许多物理像素点组成的。每个像素点可以显示多种颜色,这些颜色是通过不同的物理像素点的组合形成完整的图像。显示器颜色通常由RGB三种基色组成,这决定了每个像素点可以显示多少种颜色。比如,一个拥有1600万种颜色的屏幕,即每个基本色(R、G、B)深度扩展至8 bit(位),颜色深度越深,所能显示的色彩更加丰富靓丽。
为了更新屏幕画面,显示器以一定的频率进行刷新,如一部60Hz的手机屏幕每秒刷新60次。刷新过程中,显示器会发出垂直同步信号(如vsync)用于同步CPU、GPU和显示器的协作。GPU的主要作用是确定每个像素点最终的色值,渲染后放入帧缓冲区,视频控制器根据垂直同步信号从帧缓冲区取帧数据,最后传递给显示器进行显示。
2.生产消费者模型
中国自78年的改革开放以来,从“加工”到“制造”是技术升级的过程,当前,国家重点扶持“高端制造”和“技术创新”。从中美贸易战可以看出,国家这么做的原因是为了避免在技术上被制约。我们也可以从中受益,最初我们可能只是一名普通的加工工人,缺乏核心竞争力。但是,一旦掌握了核心技术并能够灵活应用,实现技术创新,我们的核心竞争力将凸显,不会受制于他人,掌握自己的命运。
生产者消费者模型在工作和生活中都非常常见。事实上,整个Flutter渲染框架也是按照这种流程运作的。假设Flutter 渲染流程是一个生产消费者模型,那么在这个模型中有下面几个关键环节:
对于开发者而言,接触核心技术的难度较大,而且可能与前端开发工程师的工作职责关系不大。然而,如果你作为一名出色的企业家,没有核心技术的支撑,就无法推出像Flutter这样出色的跨端技术栈。因此,尽管我们可能不需要深入掌握“核心技术”,但掌握“加工”和“制造技术”仍然是非常重要的需求。
2.1 原材料
在Flutter中,开发者本身就是原材料供应商。根据Flutter中“万物皆可Widget”的原则,开发者提供的原材料实际上是“Widget树”。
通过官方文档的引导,我们可以轻松开始Flutter开发并提供原材料。然而,正因为这样的简单易行,竞争也更加激烈。为了增强自身的核心竞争力,掌握加工和制造技术是势在必行的。
作为原材料供应商,我们向“加工厂”提供了加工所需原材料。此时,加工厂开始运作。
2.2 加工厂
在Flutter中,Flutter UI框架就是加工厂,负责构建widget树来描述UI界面的外观和行为。在这个加工厂中分为2个流水线和5个环节:
原材料组装
在Flutter中,widget的重新构建可以看作是流水线中的一个环节。每当widget的状态发生变化时,Flutter框架会调用widget的build方法来重新构建该widget及其子树的UI界面。
具体来说,widget的build方法会根据当前的状态和属性等信息,返回一个新的widget树。这个新的widget树将替换之前的widget树,成为下一次UI渲染的基础。
在流水线中,widget的重新构建相当于生产线上的一次升级。它可以改进产品的质量、性能等特性,并影响到后续阶段的加工过程。例如,如果新的widget树比之前的更简单,那么在布局、绘制和合成阶段都可以减少计算和操作,从而提高整个UI渲染的效率。
在Flutter中,widget的重新构建是UI渲染流水线中的一个环节,整个环节通过一个关键类BuildOwner管理,相当于,它就相当于一个组装工人,作用是通过组装可以改进产品的质量、性能等特性,并影响到后续阶段的“材料加工”过程。
材料加工
可以将Flutter的UI渲染过程看作是一条材料加工的流水线,其中包括布局、绘制和合成三个阶段,具体如下:
-
布局阶段:在这个阶段,Flutter UI框架根据widget树的描述,计算出每个widget在UI界面上的位置和大小,并确定widget之间的相对位置关系。这个过程类似于排版,可以看作是流水线的第一道工序。
-
绘制阶段:在这个阶段,Flutter引擎将widget树转换为渲染对象,并进行绘制。这个过程包括创建各种绘制指令,比如画线、填充颜色等,将这些指令交给Skia。这个过程类似于生产线的第二道工序。
-
合成阶段:在这个阶段,Flutter引擎将所有渲染对象按照图层的层级关系进行合成。这个过程类似于生产线的最后一道工序,将之前加工出的各个部分组装起来,形成完整的产品。
总之,Flutter的UI渲染过程可以看作是一条流水线,包括布局、绘制和合成三个阶段,每个阶段都有不同的功能和任务,整个环节通过一个关键类PipeOwner管理,他就相当于一个流水线管理者,作用是最终将所有阶段的结果合并成为制造商“Skia引擎”所需要的Layer数据。
2.3 制造
实际对于加工流程来说,Skia也算是加工材料的消费者,只不过对于整个大的流程来讲,Skia并不是最终的消费者,也仅仅是作为最终显示渲染数据的制造商,相对于一个加工厂,制造企业多了很多的核心技术,那么Skia的核心技术又是什么了?
Skia是一个用于图形处理的开源2D图形库,可以将其比作一个制造企业,可以通过一系列工具和流程来生产和处理图像和图形。以下是一些可以用来描述Skia的制造类比:
- 制造基础材料:Skia提供了一些基础材料,如颜色、画笔和画布等,这些材料可以用于构建各种图形和图像。
- 加工图形:使用Skia可以创建各种形状的图形,如圆形、矩形、椭圆形和多边形等。可以对这些图形进行各种操作,如缩放、旋转、裁剪和变形等。
- 渲染图像:Skia可以使用多种方式来渲染图像,包括CPU、GPU和矢量渲染器等。这使得Skia可以适应各种硬件和软件环境。
- 提供高级工具:除了基本的图形处理工具外,Skia还提供了一些高级工具,如滤镜、阴影、遮罩和混合模式等。这些工具可以用来创建更加复杂的图形和效果。
- 优化性能:为了提高图形处理的效率和性能,Skia使用了各种技术和算法,如渲染引擎的多线程处理、图像压缩和颜色空间转换等。
整体来讲,Skia是一个功能强大的2D图形库,类比于一个制造商,可以帮助开发者快速创建和处理各种图像和图形,并提供了各种工具和技术来优化性能和效果,生成符合GPU要求格式的位图数据。
2.4 底层核心技术
GPU渲染、操作系统基础图形API以及帧缓存技术涉及到底层核心技术,是整个生产过程中非常重要的加工制造环节,这些技术在第一章已经介绍过。它们协同作用,生成屏幕显示所需的图像数据。
笔者对于这部分的细节掌握也不够彻底,在这里就不做分享,有兴趣的同学可以自行查资料。
2.5 消费者
消费者是屏幕,屏幕自不必多说,对于我们来说,是日常随时会接触到的存在。
屏幕是计算机、手机、平板电脑等设备上用于显示图像、文本和视频等内容的输出设备。它由一个平面面板组成,通常使用液晶(LCD)、有机发光二极管(OLED)、等离子体或其他技术来显示图像。
屏幕的分辨率是指屏幕上像素的数量。分辨率越高,屏幕上显示的图像就越清晰。屏幕的刷新率是指屏幕每秒更新图像的次数。刷新率越高,图像就越流畅,特别是在观看视频或玩游戏时。
屏幕的尺寸也是一个重要的参数。屏幕的尺寸越大,屏幕上的图像就越大,更加适合用于观看视频或进行多任务处理。但是,屏幕尺寸越大,设备也会越大和笨重。
简而言之,屏幕是电子设备上用于显示图像和文本的重要输出设备,其分辨率、刷新率、类型和尺寸等参数都会对设备的使用体验产生影响。
3.总结与展望
本篇是Flutter渲染系列的第一篇,主要介绍渲染流程的基本概念及流程:
- 第一章将介绍几个结构性的渲染流程思维,以便读者更好地理解整个渲染流程,拥有一个结构型思维。
- 第二章将通过生产者-消费者模型深入探讨渲染流程,帮助读者更深入地理解渲染流程。
在笔者的计划中,Flutter渲染系列将从整体到局部逐步介绍Flutter渲染原理。首先,本篇对整个渲染流程进行基本介绍,随后逐步深入细节。
第二篇文章将基于生产者-消费者模型,对UI框架的加工流程基于源码进行详细分析,具体可参见Flutter渲染原理系列(一)——UI加工厂之产品需求。