likes
comments
collection
share

深入Flutter渲染更新机制一

作者站长头像
站长
· 阅读数 2

深入Flutter渲染更新机制一

在学习Flutter的过程中大家都知道调用setState方法后会进行UI的更新,今天来深入的解析下这其中的过程原理,更好的理解下Flutter的更新机制。

先来看下相关的时序图:

UI更新时序图

深入Flutter渲染更新机制一

一.State 类

1.1 先来看下我们第一步调用的setState方法内部,在这里可以看到它调用的是Element类中的markNeedsBuild()方法;

深入Flutter渲染更新机制一

二.Element 类

2.1 在markNeedsBuild()这个方法内部,它做了二件事,第一件事是将当前的element标为脏数据,第二件事是调用了BuildOwner 这个类中的scheduleBuildFor方法;BuildOwner 这个类是一个单例,在应用初始化的过程中进行了单例初始化,它负责管理着element对象的生命周期;

深入Flutter渲染更新机制一

三.BuildOwner 类

3.1 调用onBuildScheduled方法;并将当前的脏数据element添加到脏数据列中;那这里的onBuildScheduled方法是什么呢?它起到什么作用呢?前面讲到BuildOwner是个单例,我们看下BuildOwner的初始化过程;

深入Flutter渲染更新机制一

四.WidgetsBinding

4.1 从BuildOwner的初始化可以看出来,上面onBuildScheduled方法回调的是_handleBuildScheduled方法;再往下看,发现最终调用的是一个SchedulerBinding 类中的方法了;

深入Flutter渲染更新机制一

五.SchedulerBinding

5.1 SchedulerBinding 也是一个单例;这里可以看到ensureVisualUpdate 内部调用的是 scheduleFrame ;在scheduleFrame 内部可以看到调用了二个方法,一个是注册渲染回调事件ensureFrameCallbacksRegistered,一个是调用PlatformDispatcher 类中的scheduleFrame 方法;

深入Flutter渲染更新机制一

5.2 它提供了一个**scheduleFrame()** 方法,该方法通知 Flutter 引擎准备好执行下一帧的渲染工作;在通知渲染前,它调用了ensureFrameCallbacksRegistered 方法,注册了二个回调事件;注册完成事件后,调用了PlatformDispatcher 中的scheduleFrame方法;

深入Flutter渲染更新机制一

5.3 注册回调事件;这二个回调事件比较关键,是在flutter端真正进行视图更新的地方;

深入Flutter渲染更新机制一

六. PlatformDispatcher

6.1 从定义可以看出这个方法是一个调用了native层的方法,后面的流程就是由底层c++代码开发的;由引擎层去控制了;那这个方法是什么作用呢?这个方法其实是通知引擎层,告诉GPU可以刷新页面了;在Flutter中整个渲染可以分为UI线程和GPU线程二个线程来完成的,在调用scheduleFrame方法后就通知到GPU线程了;

深入Flutter渲染更新机制一

💡 那UI线程与GPU线程是如何保证渲染同步的呢?

在 Flutter 中,引入了Vsync机制;Vsync是一个信号机制,当GPU进行渲染前会发出一个信号通知Flutter进行每一帧的渲染了;这时Flutter端会将构建好的界面通过 Layer Tree 的形式发送给 GPU 线程;GPU 线程收到 Layer Tree 后,会根据 Vsync 信号开始渲染当前帧的内容; Vsync用于将 UI 线程和 GPU 线程的渲染操作同步起来,以达到更流畅的渲染效果。

具体来说,Flutter 的渲染过程是通过两个线程来实现的:UI 线程和 GPU 线程。UI 线程负责构建界面,GPU 线程负责将界面渲染到屏幕上。为了保证两个线程的同步和协作,Flutter 使用了 Vsync 机制。

七. SingletonFlutterWindow

7.1 在第七步已经通知GPU进行数据刷新了,那GPU线程是什么时候获取Flutter端的Layer Tree信息进行渲染的呢?GPU线程也是通过navite方法调用到Flutter端的;那具体是调用的那个方法呢?是的,没看错,调用的是onBeginFrame和onDrawFrame这二个方法;从官方的注释也可以看出,这二个方法也是必须在调用了scheduleFrame之后才会调用的,以保证UI线程与GPU线程渲染的顺序。

深入Flutter渲染更新机制一

深入Flutter渲染更新机制一

八. SchedulerBinding

8.1 从5.3中我们可以看到,onBeginFrame方法是赋值的_handleBeginFrame方法;这个方法应该是处理一些绘制前的一些回调,在每一次的绘制前都会调用这个方法,处理一些回调;

深入Flutter渲染更新机制一 深入Flutter渲染更新机制一

8.2 在Flutter端真正开始绘制是从这个方法开始的;

深入Flutter渲染更新机制一

8.3 从下面二个方法可以看到内部调用的是一个_persistentCallbacks注册的回调方法;而_persistentCallbacks方法的赋值是什么时候呢?这个就要从Flutter入口方法runApp说起了;

深入Flutter渲染更新机制一

深入Flutter渲染更新机制一

九. WidgetsBinding

9.1 当Flutter应用启动的时候最先开始调用的是runApp这个方法

深入Flutter渲染更新机制一

9.2 可以看到WidgetsFlutterBinding 类with了多个类,有一个RendererBinding 类,看下这个类的初始化;

深入Flutter渲染更新机制一

十.RendererBinding

10.1 从这可以看出在这里我们给8.3中的回调方法赋值了,最终页面渲染在Flutter端调用到了_handlePersistentFrameCallback 这个方法;在内部调用了drawFrame方法,终于看到了我们熟悉的方法;

深入Flutter渲染更新机制一

深入Flutter渲染更新机制一

十一. WidgetsBinding

11.1 上面drawFrame方法调用到了WidgetsBinding 类中;看下buildScope方法内部;

深入Flutter渲染更新机制一

十二. BuildOwner 类

12.1 从3.1中我们添加到脏数据列表中的数据,在这里我们取出脏数据,并且调用了element.reduild方法;

深入Flutter渲染更新机制一

十三.Element

13.1 可以看到内部调用的performRebuild方法是一个抽象方法,不同的Element子类实现有不同;我们以ComponentElement类的实现看下实现,看到了我们熟悉的build方法了;至此,我们开始了页面的渲染。

深入Flutter渲染更新机制一 深入Flutter渲染更新机制一

相关文章:

转载自:https://juejin.cn/post/7235309338096435260
评论
请登录