Flutter的启动和渲染流程

一、Flutter的启动流程

1、Flutter启动初始化

在安卓平台上启动App时,会先创建应用进程,然后创建FlutterApplication并执行其onCreate方法。在FlutterApplication的onCreate方法中,会执行Flutter相关的初始化,主要包括Flutter编译产物相关名称和路径的初始化、处理平台侧和Flutter侧Vsync信号的同步、加载引擎代码libflutter.so库、为Flutter创建存储目录等操作。

VsyncWaiter的初始化方法中,创建了原生平台层和Flutter引擎层同步Vsync信号的代理对象asyncWaitForVsyncDelegate。当Flutter侧需要刷新UI界面时,通过asyncWaitForVsyncDelegate和FlutterJNI将原生平台收到的Vsync回调转发给自身,然后在触发渲染流程更新界面。

下图是启动初始化的调用流程图:

在这里插入图片描述

2、FlutterActivity引擎获取

在FlutterActivity的onCreate方法中,通过调用delegate的onAttach方法获取Flutter引擎。引擎的获取主要分为三个步骤:

  1. 首先,从FlutterEngineCache中尝试获取已缓存的FlutterEngine
  2. 如果缓存中没有可用的FlutterEngine,则从provideFlutterEngine方法中获取自定义的FlutterEngine
  3. 如果以上两种方式都无法获取到FlutterEngine,那么将通过FlutterEngineGroup创建新的FlutterEngine

下图是FlutterActivity引擎获取的调用流程图:

在这里插入图片描述

3、FlutterEngineGroup创建引擎

Flutter引擎的创建有两种方式,一种是直接创建,一种是通过EngineGroup创建。通过EngineGroup方式创建的引擎之间能够共享部分资源(例如 GPU 上下文、字体度量和隔离线程的快照),从而加快首次渲染的速度、降低延迟并降低内存占用,每增加一个引擎只会增加约 180K 的内存占用。

FlutterEngineGroup创建引擎时,如果还没有创建过引擎,那么就会直接创建第一个引擎。如果已经有存在的引擎了,那么就会通过spawn部分资源共享的方式创建新引擎。

创建引擎时,会创建Dart侧的执行入口DartEntrypoint,如果提供自定义入口函数了,那DartEntrypoint中包含的就是自定义的入口函数名。如果没有提供自定义的入口函数,那么DartEntrypoint中包含的就是默认的入口函数名“main”。

创建引擎时,还会注册平台消息handler,创建平台系统channel,用于Flutter端和原生端通信。

创建引擎时,还会初始化Flutter环境、DartVM、FlutterEngine,关联FlutterJNI和Engine便于平台和引擎通信。创建FlutterRender对象,最终会执行Dart侧的入口方法,执行Dart代码。

下图是通过EngineGroup方式创建引擎的调用流程图:

在这里插入图片描述

二、Flutter的渲染流程

1、FlutterActivity视图渲染

FlutterActivity通过FlutterView呈现Flutter画面,并实现渲染显示。FlutterView继承自FrameLayout,它本身也是一个View。实际上,FlutterView的渲染是通过其内部的FlutterSurfaceView或FlutterTextureView(两者都是RenderSurface的实现类,不考虑FlutterImageView)来真正进行的。选择使用FlutterSurfaceView还是FlutterTextureView是根据RenderMode来决定的。

在FlutterView与Flutter引擎建立关联时,FlutterSurfaceView或FlutterTextureView也会与引擎的FlutterRenderer建立关联。Dart侧编写的Widget渲染树会交给引擎进行渲染,而FlutterRenderer负责将Flutter引擎的画面数据渲染到FlutterSurfaceView或FlutterTextureView上。渲染数据是通过FlutterJNI进行Engine与Android层之间传递的,最终将画面显示到原生平台视图中。

下图是FlutterActivity视图渲染的调用流程图:

在这里插入图片描述

2、Dart树渲染流程

Dart程序的执行是从入口方法(默认为main方法)开始的,接着会调用WidgetsBinding的scheduleAttachRootWidget方法,根据Dart业务代码构建出三棵树。然后,通过调用SchedulerBinding的scheduleWarmUpFrame方法启动渲染流程。最终,在RendererBinding的drawFrame方法中,将会调用PipelineOwner进行布局、合成、绘制等一系列操作。最后,通过调用Skia将视图绘制到屏幕上。

当Widget的状态需要变更时,我们可以调用State.setState来触发这个过程。首先,将会对发生变化的元素进行标记,并将其添加到_dirtyElements这个脏元素列表中。然后,通知Flutter引擎需要刷新用户界面。在Flutter引擎层,会向平台层注册Vsync信号回调。一旦Vsync信号到达,就会开始触发渲染流程。首先会对_dirtyElements中的元素进行重建和更新,生成更新后的渲染树。最终,在RendererBinding的drawFrame方法中,将会调用PipelineOwner进行布局、合成、绘制等一系列操作。最后,通过调用Skia将视图绘制到屏幕上。

下图是Dart树渲染的调用流程图:

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Flutter渲染机制可以从源码角度来理解。Flutter渲染与两个线程直接相关,分别是UI线程和GPU线程。UI线程负责执行Dart root isolate代码,并将其转换为Layer tree。 Layer 是 Flutter Framework 中的一个重要概念,它代表了一块矩形区域,可以包含图形、文本、图片等内容。这些 Layer 最终会被提交到 Engine 中进行绘制。 Layer 的工作原理是将所有的绘制操作转化为一系列的绘制指令,然后将这些指令传递给 GPU 线程进行绘制。 Flutter Framework 中的绘制过程经过多个步骤,包括布局、绘制、合成等,最终将所有的 Layer 组合在一起形成最终的界面。通过理解 Flutter渲染原理,开发者可以更清晰地了解应用程序的渲染过程,并进行性能优化。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Flutter渲染机制—UI线程](https://download.csdn.net/download/weixin_38550834/15446392)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Flutter 画面渲染的全面解析](https://blog.csdn.net/chengjiamei/article/details/107974790)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值