Flutter渲染流程总览
Flutter框架存在渲染流水线(
Rendering pipline), 由垂直同步信号(Vsync)驱动,Vsync信号由系统提供. 当Flutter接收到Vsync信号后,会按照图示顺序执行一系列动作: 动画(Animate) -> 构建(Build) -> 布局(Layout) -> 绘制(Paint), 最终生成一个场景(Scene)之后送往底层,由GPU绘制到屏幕上.
- 动画(
Animate): 是渲染流水线的第一个阶段, 随着接收到的Vsync信号改变状态(State) - 构建(
Build): 需要重新构建的Widget在此阶段会重新构建, 也就是调用StatlessWidget.build()或者State.build()的时候 - 布局(
Layout): 调用RenderObject.performLayout(), 确认元素的位置和尺寸 - 绘制(
Paint): 调用RenderObject.paint(), 将渲染对象绘制到上下文(Context)中
以上是整个渲染流水线(Rendering pipline)大致工作流程.
Flutter app 只有在状态发生变化的时候才会触发渲染流水线(Rendering Pipline). 当调用State.setState()时, Flutter经过一系列处理,最终会发起一个调度信号Vsync给底层. 底层在接受Vsync信号后,开始驱动渲染流水线开始运作,最后把新页面显示在屏幕上.
Flutter架构层
Flutter 被设计为一个可扩展的分层系统.它可以被看成是每个独立的组件的系列合集, 上层组件各自依赖下层组件.组件无法越权访问更底层的内容, 并且框架层中的各个部分是可选且替代的.
- 框架 (
Framework) 部分使用Dart语言编写 - 引擎 (
Engine) 部分使用C++进行实现, 引擎为框架提供支撑,也是连接框架和平台 (Android/IOS) 的桥梁.
引擎Engine将底层C++代码包装成Dart代码, 通过dart:ui暴露给Flutter框架层, 该库暴露了最底层的原语, 包括用于驱动输入、图形、和文本渲染的子系统类.
触发流水线的Vsync信号来自引擎(Engine), 渲染完成以后的场景最终会回到引擎显示,并且Vsync信号的调度也是框架(Framework)通过引擎(Engine)来通知系统的.
渲染流程从框架(Framework)和引擎(Engine)交互的角度看,就是下图这样子:
- 框架(
Framework)通过scheduleFrame通知引擎(Engine)需要调度一帧 - 在接收到
Vsync信号后,引擎(Engine)首先会回调框架(Framework)的_beginFrame函数,此时渲染流水线(Rending Pipline)进入动画(Animate)阶段. - 在动画(
Animate)阶段完成以后. 引擎(Engine)接着会处理微任务队列(Microtask queue) - 微任务(
Microtask)执行完, 接着会执行框架(Framework)的_drawFrame函数. 渲染流水线继续按序执行构建(Build)、布局(Layout)和绘制(Paint). - 绘制(
Paint)结束以后,框架调用render将绘制完成的场景送入引擎(Engine), 显示在屏幕上.
Window
Flutter中的Window来自库dart:ui, 相关源代码在window.dart中.
在Flutter中, Window是个单例:
/// The [Window] singleton. This object exposes the size of the display, the
/// core scheduler API, the input event callback, the graphics drawing API, and
/// other such core services.
final Window window = new Window._();
Window单例对上层提供屏幕尺寸, 调度接口, 输入事件回调, 图形绘制接口以及其它一些核心服务. 总体来说, Window集中提供了Flutter引擎中和图形界面相关的API.
Window中和渲染流水线相关的API如下:
// vsync信号到来以后的回调
FrameCallback _onBeginFrame;
VoidCallback _onDrawFrame;
// 请求引擎engine调度一帧
void scheduleFrame() native 'Window_scheduleFrame';
// 绘制完成以后将场景送入引擎engine显示
void render(Scene scene) native 'Window_render';
注意一下函数名称后面的 native 关键字,native表明这个函数是调用到engine层的.和Android中的jni调用类似.
除渲染相关的API, window中还有其他一些重要的API
// 触摸事件的回调
PointerDataPacketCallback _onPointerDataPacket;
// 获取启动时初始页面的路由
String _defaultRouteName() native 'Window_defaultRouteName';
// 发送PlatformMessage. 这个是Platform channels机制的一部分
String _sendPlatformMessage(
String name,
PlatformMessageResponseCallback callback,
ByteData data,
) native 'Window_sendPlatformMessage;
// 收到platform message后的回调
PlatformMessageCallback _onPlatformMessage;
还有一些和local,accessbility相关的API就不列出来了.
总结
Window总体并不算复杂, 基本上是engine层对上层提供的和用户界面相关的接口的封装. Flutter框架是基于Window建立起来的.
有可能的话, 完全可以基于Window搭建起自己的一套框架.