Flutter UI框架

281 阅读5分钟

UI框架特指:基于一个平台,在此平台上实现一个能快速开发GUI(图形用户接口)的框架,平台通常指浏览器或操作系统。通常平台只提供非常基础的图形API,比如划线、画几何图形等,大多数平台中,这些基础的图形API通常会被封装在一个Canvas对象中集中管理,如果直接使用Canvas来构建用户界面是非常复杂且麻烦的事情,所以,UI框架解决的主要问题就是:如果基于基础的图形API(Canvas)来封装一套可以高效创建UI的框架。
通常各个平台的UI框架的实现原理基本是相通的,无论Android还是iOS,它们将一个用户界面展示到屏幕的流程是相似的。通常一个操作系统从上到下分为框架层、引擎层和嵌入层,大多开发基本都是与框架层打交道。回顾之前Flutter的结构图。

image.png

硬件绘图的基本原理

屏幕显示图像的基本原理:
显示器(屏幕)是由一个个物理显示单元组成,每一个单元称之为物理像素点,而每一个像素点可以发出多种颜色,显示器成像的原理就是在不同的物理像素点上显示不同的颜色,最终构成完整的图像。

一个像素点能发出的所有颜色总数是显示器的一个重要指标,比如1600万色的屏幕就是指一个像素点可以显示出1600万种颜色,而显示器颜色是由RGB三基色组成,所以1600万基2的24次方,即每个基本色(R、G、B)深度扩展至8bit(位),颜色深度越深,所能显示的色彩更加丰富靓丽。

为了更新显示画面,显示器是以固定的频率刷新(从GPU取数据),比如手机的屏幕刷新频率为60Hz。当一帧(frame)图像绘制完成后,准备绘制下一帧时,显示器会发出一个垂直同步信号(如vsync),60Hz的屏幕就会一秒内发出60次这样的信号。这个信号主要是用于同步CPU、GPU和显示器的,一般来讲,计算机系统中,CPU、GPU、显示器是以一种特定的方式协作:CPU将计算好的显示内容提交给GPU,GPU渲染后放入帧缓冲区,然后视频控制器按照同步信号从帧缓冲区取帧数据传递给显示器。

CPU和GPU的任务各有偏重,CPU主要用于基本的数学和逻辑计算,而GPU主要执行图形处理相关的复杂的数学,如矩阵变化和几何计算,GPU的主要作用是确定最终输送给显示器的各个像素点的色值。

操作系统的绘制API封装

由于最终的图形计算和绘制都是由相应的硬件来完成,而直接操作硬件的指令通常都会有操作系统屏蔽,应用开发者通常不会直接面对硬件,操作系统屏蔽了这些底层的硬件操作后,会提供一些封装后的API供操作系统之上的应用调用,但是对于应用开发者来说,直接调用这些操作系统提供的API是比较复杂和低效的,因为操作系统的API往往比较基础,直接调用需要了解API的很多细节,因此,几乎所有用于开发GUI程序的编程语言都会在操作系统之上再封装一层,将操作系统原生API封装在一个编程框架和模型中,然后定义一种简单的开发规则来开发GUI应用程序,而这一层抽象,就是UI框架。如iOS的UIKit对View的抽象,都将操作系统API抽象成一个基础对象(如用于2D图形绘制的Canvas),然后再定义一套规则来描述UI,如树结构,UI操作的单线程原则等。

Flutter UI框架

Flutter框架是使用同一种编程语言,然后针对不同操作系统API抽象一个对上接口一致,对下适配不同操作系统的中间层,然后在打包编译时,再使用相应的中间层代码。它提供了一套Dart API,然后底层通过OpenGL这种跨平台的绘制库(内部会调用操作系统API)实现一套代码跨多端。由于Dart API也是调用操作系统API,所以性能接近原生。

  • 虽然Dart是先调用OpenGL,OpenGL才会调用操作系统API,但是这仍然是原生渲染,因为OpenGL只是操作系统API的一个封装库,它并不像WebView渲染那样需要JavaScript运行环境和CSS渲染器,所以不会有性能丢失。
  • Flutter早期版本底层会调用OpenGL这样的跨平台库,更新版本后,在iOS设备上使用苹果提供的Metal,因为在iOS设备上,使用Metal可以获得比OpenGL更好的绘制性能,只有当Metal不可用时才会降级调用OpenGL。