引擎盖下颤振:绑定

本文是我上一篇文章的直接延续



为全面了解,我建议您先阅读链接上指示的文章或在您的记忆中刷新它。在其中,我分析了Flutter设备的重要方面之一-树木之间的相互作用以及树木之间的责任分配。但是,问题仍然悬而未决:第一部分中描述的整个机制的运作是如何组织的?这就是我们将在本文中尝试理解的内容。







一般规定



如果您打开Flutter技术概述,则在以下几点中,我们将看到下图。它显示了框架作者自己将其划分为的条件级别。 



Flutter框架方案


实际上,正如他们自己所说的,我们看到了一个粉扑蛋糕。可以区分更大或更小的层。



框架级别是编写应用程序时使用的所有内容,以及允许我们与已编写的引擎级别进行交互的所有实用程序类。与该级别相关的所有内容均使用Dart编写。



引擎级别-比框架级别低的级别,包含允许框架级别工作的类和库。包括虚拟机Dart,Skia等



平台级别-特定于特定启动平台的特定于平台的 机制。



让我们仔细看一下框架级别。在图中,以从较高级别到较低级别的层的形式显示。在最底部,我们看到了一层基础顾名思义,该层是框架级别的基础和基础。我们找到了这个库,这就是它的描述中写的:



Core Flutter框架原语。

该库中定义的功能是Flutter框架的所有其他层使用的最低级别的实用程序类和功能。




该库中定义的函数是Flutter框架的所有其他层使用的实用工具类和最低级别的函数。



该库还包含BindingBase-所有Binding的基类。



捆绑



首先,让我们了解什么是Binding以及Flutter中如何使用Binding。这个名字本身告诉我们,这是某种联系。 Flutter命令留给BaseBinding的文档向我们介绍了以下内容:



提供单例服务(也称为“绑定”)的mixin的基类。要在mixin的on子句中使用此类,请从其继承并实现[initInstances()]。保证mixin在应用程序的生命周期内仅构造一次(更确切地说,如果在检查模式下构造两次,它将断言)。



这是各种通信服务的基类,以mixin的形式出现。每个这样的mixin都会被初始化,并保证其实例在应用程序生命周期中的唯一性。



基本绑定是一个基本的抽象类,然后让我们看一下绑定的具体实现。其中,我们将看到:



ServicesBinding负责将消息从当前平台转发到消息数据处理程序(BinaryMessenger);



PaintingBinding负责与渲染库进行通信。



RenderBinding负责渲染树和Flutter引擎之间的通信。



WidgetBinding负责小部件树和Flutter引擎之间的通信。



SchedulerBinding是用于常规任务的调度程序,例如:



  • 调用系统在Window.onBeginFrame中启动的传入回调-例如,股票行情指示器和动画控制器的事件;
  • 调用Window.onDrawFrame系统启动的连续回调,例如,在传入的回调完成后,事件以更新显示系统;
  • 框架后回调,在从Windows.onDrawFrame返回之前,在连续回调之后调用;
  • 必须在帧之间执行的非渲染任务。


SemanticsBinding负责链接语义层和Flutter引擎。



GestureBinding负责使用手势子系统。



顾名思义,绑定是Flutter引擎级和框架级本身之间的通信层,每个层都负责特定的工作方向。



WidgetsFlutterBinding



为了更好地理解它们如何协同工作,让我们看一下任何Flutter应用程序的起点-runApp调用。我们正在调用的方法在binding.dart文件中,这不是巧合。它的描述说,它扩展了传递的应用程序小部件并将其附加到屏幕上。让我们看看它的作用:



void runApp(Widget app) {
  WidgetsFlutterBinding.ensureInitialized()
    ..scheduleAttachRootWidget(app)
    ..scheduleWarmUpFrame();
}


我们在这里遇到WidgetsFlutterBinding,这是基于小部件框架的应用程序绑定的具体实现。它的核心是将Flutter框架和引擎结合在一起的粘合剂。该WidgetsFlutterBinding由许多的绑定,我们前面讨论:GestureBindingServicesBindingSchedulerBindingPaintingBindingSemanticsBindingRendererBindingWidgetsBinding。因此,我们得到了一个可以在所有必要方向上将我们的应用程序与Flutter引擎连接的层。



让我们回到启动应用程序。在WidgetsFlutterBinding中scheduleAttachRootWidgetscheduleWarmUpFrame方法被称为,让我们看看它们发生了什么。



ScheduleAttachRootWidget



scheduleAttachRootWidget 方法attachRootWidget的延迟实现此方法属于WidgetsBinding它的描述说它将附加的窗口小部件附加到renderViewElement-元素树的根元素。 



void attachRootWidget(Widget rootWidget) {
    _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
      container: renderView,
      debugShortDescription: '[root]',
      child: rootWidget,
    ).attachToRenderTree(buildOwner, renderViewElement);
}


从代码中,我们可以看到此方法创建了RenderObjectToWidgetAdapter,它是窗口小部件树的根窗口小部件,并用作将树相互连接的桥梁。查看其实现,我们将看到它不会为其自身创建RenderObject,而是从容器字段返回一个值,并且在创建它时将RendererBinding中的renderView传递给它。此renderView是渲染树的根元素。



RenderView获取renderView => _pipelineOwner.rootNode;



PipelineOwner实际上是管理渲染过程的经理。



返回attachRootWidget方法... 在创建的适配器上调用attachToRenderTree方法,我们使用它首次创建元素树的根。应该注意的是,buildOwner被传递给attachToRenderTree方法此类是窗口小部件树构建管理器,它监视窗口小部件的状态,监视更新的需要并执行许多其他与更新窗口小部件树的状态有关的重要任务。因此,我们得到了非常多的三棵Flutter树,每棵都通过Bindings存储和管理。



ScheduleWarmUpFrame



scheduleWarmUpFrame 方法属于SchedulerBinding,用于调度帧以尽快开始,而无需等待系统信号“ Vsync”。由于该方法是在应用程序启动期间使用的,因此可能很昂贵的第一帧将花费一些额外的时间来启动。此方法阻止事件的调度,直到调度的帧完成为止。



正如我们所看到的,启动时启动的两种机制都与各种绑定相关并与之交互,而绑定又紧密相关并提供与系统的交互。让我们用下图进行总结。







结论



绑定是组织Flutter应用程序的重要机制。正是他将应用程序的各个方面以及引擎与彼此联系起来。



包括感谢他,我们可以在框架的最高级部分编写应用程序,而不必担心我们如何组织其他所有事情的连贯工作。我希望本文能帮助您了解Flutter设备的这一部分。



感谢您的关注!



所用材料:



Flutter

https://flutter.dev/



All Articles