相关类
- Canvas:封装了Flutter Skia各种绘制指令,比如画线、画圆、画矩形等指令。
- Layer:分为容器类和绘制类两种;暂时可以理解为是绘制产物的载体,比如调用 Canvas 的绘制 API 后,相应的绘制产物被保存在 PictureLayer.picture 对象中。
- Scene:屏幕上将要要显示的元素。在上屏前,我们需要将Layer中保存的绘制产物关联到 Scene 上。
- Picture:是一系列的图形绘制操作指令。
- Container Layer:管理Layers,是唯一可以拥有child layer的Layer;
- 非Container Layer:真正用于承载渲染结果的layer,在Layer Tree中属于叶子结点。比如PictureLayer承载的是图片的渲染结果,TextureLayer承载的是纹理的渲染结果;
绘制流程
大致流程
- 构建一个 Canvas,用于绘制;同时还需要创建一个绘制指令记录器,因为绘制指令最终是要传递给 Skia 的,而 Canvas 可能会连续发起多条绘制指令,指令记录器用于收集 Canvas 在一段时间内所有的绘制指令,因此Canvas 构造函数第一个参数必须传递一个 PictureRecorder 实例。
- Canvas 绘制完成后,通过 PictureRecorder 获取绘制产物,然后将其保存在 Layer 中。
- renderView.compositeFrame构建 Scene 对象,将 layer 的绘制产物和 Scene 关联起来。
- 上屏;调用window.render API 将Scene上的绘制产物发送给GPU。
精细流程
第一次绘制时,从上到下递归绘制子节点,每当遇到一个边界节点,判断如果该节点的layer属性是否为空,是就创建一个新的OffsetLayer并赋值给它;不是则使用。然后将layer传递给子节点,接下来:
- 如果子节点是非边界节点,且需要绘制,则:
- 第一次绘制:创建一个Canvas对象和一个PictureLayer,然后将它们绑定,后续调用Canvas绘制都会落到和其绑定的PictureLayer上,接着这个PictureLayer会加入到边界节点的layer中;
- 不是第一次绘制:复用已有的边界节点和Canvas对象;
- 如果子节点是边界节点,则对子节点递归上述过程。当子树递归完成后,就要将子节点的layer添加到父级layer中。
RenderObject调用markNeedsRepaint来发起重绘:
- 从当前节点一直往父级查找,直到找到一个绘制边界点时终止查找,然后会将该绘制边界点添加到其PiplineOwner的_nodesNeedingPaint列表中。
- 在查找的过程中,会将自己到绘制边界点路径上所有节点的_needPaint属性设置为true,表示需要重绘。
- 请求新的frame,执行重绘流程。下一个frame就会走drawFrame流程,涉及到flushCompositingBits、flushPaint 和 compositeFrame 三个函数。
参考
- Flutter UI 渲染浅析(一)总览
- Flutter UI 渲染浅析(二)VSync 注册
- Flutter UI 渲染浅析(三)Animation 原理
- Flutter UI 渲染浅析(四)Build
- Flutter UI 渲染浅析(五)Layout
- Flutter UI 渲染浅析(六)Paint
- Flutter UI 渲染浅析(七)Composite
- 《Flutter框架分析(一)– 总览和Window》
- 《Flutter框架分析(二)– 初始化》
- 《Flutter框架分析(三)– Widget,Element和RenderObject》
- 《Flutter框架分析(四)– Flutter框架的运行》
- 《Flutter框架分析(五)– 动画》
- 《Flutter框架分析(六)– 布局》
- 《Flutter框架分析(七)– 绘制》