1.0 Flutter框架概览

1.1 Flutter框架概览

Flutter能够实现跨平台开发,开发者更高效,性能接近原生。主要是Flutter在设计上采用了不同的模式

  • 开发期间
    Flutter App会运行在Dart VM上,开发者可以使用热重载技术实时更新代码获得反馈。
  • 正式发布
    Flutter App会预编译成二进制文件, 运行现在 Dart Precompile(只包括GC等必要功能)上,以获取最佳性能,此外Flutter还有一套高效的渲染系统,以保证足够的性能,后续会逐一了解。

1.2.1 分层架构模型

Flutter在软件设计上是一个灵活可扩展的分层架构,Flutter的每个功能组件都以库的形式存在,每个库都依赖于其下一层的库。


Flutter 分层架构

扩展: Android 乃至 OSI网络模型的架构图和Flutter的分层架构设计几乎如出一辙,《UNIX编程艺术》一书中对这种设计给出了一个贴切的称呼:正交性。由于正交性的存在,Android才有层出不穷的定制ROM,OSI才会有各有千秋的协议(如传输层的TCP/UDP)。

下面自底向上地分析Flutter的每一层

  • Embedder
    Embedder 顾名思义是将Flutter嵌入到Native平台,例如Android,IOS,乃至Linux,Windows。 Embedder的职责是为渲染UI到Surface、处理单击事件等与底层平台交互的行为提供一个入口。Embedder 使用的语言取决于具体平台,对Android来说,通常是C++和Java。
  • Engine
    Engine是Flutter的核心部分,大部分代码由C++构成。Engine的主要职责是为Flutter合成并渲染屏幕数据,并为此提供了一系列底层基础能力,包括图形绘制(通过Skia)、文字渲染、文件和网络I/O、无障碍支持、平台插件、Dart运行时管理和编译期工具链等。Engine的主要功能通过 dart:ui模块和Framework进行双向交互。
  • Framework
    通常开发者不需要感知Embedder和Engine层的存在(如果不需要调用平台的系统服务),Framework是开发者直接交互的,因而也在整个分层架构模型的最上层。Framework是有Dart语言开发,提供了一套现代的、响应式的UI框架,Framework本身也是分层的,自底向上的角色和功能介绍如下。
    1. Foundation以及Animation、Painting和Gestures提供了Framework公用的底层能力,是对Engine的抽象与封装。
    2. Rendering 主要负责Render Tree的Layout等操作,并最终将绘制指令发送到Engine进行绘制上屏。
    3. Widgets是对Rendering的一种上层封装,Render Tree虽然能最终决定UI但是过于复杂,不适合开发者使用,Widgets通过组合的思想,提供了丰富的Widget组件供开发者使用。
    4. Material 和 Cupertino 是对Widgets的进一步封装,Widgets提供的组件对开发者来说还是过于原始,因此这一层基于Android 和 IOS的设计规范提供了更完备的组件,以保证开发者开箱即用。

1.2.2 响应式Widgets

Flutter深受React影响,采用了声明式UI的写法,那自然离不开 Virtual DOWM,扮演这个角色的正式Widget。在Flutter中可以说万物皆Widget。所以在Flutter的开发中Widget往往是层层嵌套的,那么Flutter是如何保证层级嵌套过深的性能呢?

  • Widget Tree上的Widget节点越多,通过Diff算法得到需要重建的部分就越精确、范围越小,而UI渲染的主要性能瓶颈就是Widget节点的重建
  • Dart语言的对象模型和GC模型对小对象的快读分配和回收做了优化,而Widget正式这种小对象
    注: 在后续剖析渲染管道时,这部分会更详细的阐述

1.2.3 初识渲染管道

在讨论渲染管道(Rendering Pipeline)之前,首先了解Flutter三棵树模型(实际上还有一棵 Layer Tree,但是过于底层,一般不纳入讨论)

Flutter三棵树示意图

Widget Tree是开发者能够直接感知到的,但其最终形态和代码会有一些差异,因为部分Widget本身就是由其它Widget构成的。上图中的ColoredBox等Widget虽然开发者没有直接使用,但却存在于最终的Widget Tree中。每个Widget都会有对应的Element, 并有一棵对应的Element Tree,实际上Element Tree才是内存中真实存在的数据,Widget Tree和Render Tree都是由Element Tree驱动生成的。正是由于这种机制,Element Tree扮演了Virtual DOM中管理者的角色。
Element Tree中, RenderObjectElement类型的节点都会产生RenderObject并构成最终的Render Tree。对开发者来说:Render Tree时最底层的UI描述,但对Framework来说: Render Tree是Framework对UI最上层,最抽象的描述。
任何一个UI框架,无论是Web还是Android,都有自己的渲染管道,渲染管道时UI框架的核心,负责处理用户输入,生成UI描述,栅格化绘制指令,上屏最终数据等。Flutter也不例外,Flutter采用了自渲染的方式,所以渲染管道是独立于平台的。以Android为例, Flutter只是通过Embedder获取了一个Surface或Texture作为渲染管道最终的输出目标,具体来说Flutter的渲染管道分为以下七个步骤:

  1. 用户输入(User Input): 响应用户通过鼠标、键盘、触摸屏等设备产生的手势行为。
  2. 动画(Animation): 基于定时器(Timer)更新当前帧的数据。
  3. 构建(Build): 三棵树的创建,更新和销毁阶段,StatelessWidget和State的build方法将在改阶段执行。
  4. 布局(Layout): Render Tree将在该阶段完成各个节点的大小和位置计算。
  5. 绘制(Paint): Render Tree遍历每个节点,生成Layer Tree、RenderObject的paint方法在该阶段执行,生成一系列绘制指令。
  6. 合成(Composition): 处理Layer Tree,生成一个Scene对象,作为栅格化的输入。
  7. 栅格化(Rasterize):将绘制指令处理成可供GPU上屏的原始数据。

以上七个步骤中: 用户输入和动画是相对独立的过程,部分简单的静态UI不需要处理。构建、布局和绘制直接关系到Flutter三棵树的维护和使用,是Framework层的核心功能之一,是深刻理解Flutter底层工作原理的关键所在(后续文章中详细介绍)。合成和栅格化负责绘制指令的最终消费,主要逻辑在Engine中实现。

1.2.4平台嵌入与交互

虽然Flutter能够脱离平台实现自渲染,但是无法脱离平台单独存在。以Android为例,Flutter页面绘制在一个FlutterView上,FlutterView是FlutterActivity的一部分,所以一个Flutter页面和一个Activity没什么两样(后续介绍Flutter的启动流程,更好理解Flutter是如何嵌入平台的)。
除了被平台调用,Flutter还需要和平台做一些特定的交互,比如调用平台的特定方法,获取页面生命周期回调等。对于一些视频,地图,其通常只提供了特定的sdk,因而Flutter无法使用,Platform View的出现就是为了解决这一问题,它提供了一种机制,可以在Flutter页面中渲染原生组件(后续文章介绍原理)

参考书籍:
《Flutter内核源码剖析》

你可能感兴趣的:(1.0 Flutter框架概览)