Flutter框架分析(二)-- 初始化(1)

混入的那些各种绑定类也都是继承自抽象类BindingBase的。

abstract class BindingBase {
BindingBase() {

initInstances();

}

ui.Window get window => ui.window;
}

关于抽象类BindingBase,你需要了解两个地方,一个是在其构造的时候会调用函数initInstances()。这个函数会由其子类,也就是上面说那些各种混入(Mixin)的绑定类各自实现,具体的初始化都是在其内部实现的。另一个就是BindingBase有一个getter,返回的是window。还记得在《Flutter框架分析(一)-- 总览和Window》中提到过的窗口吗?没错,这里的window就是它。那我们是不是可以推论,这些个绑定其实就是对window的封装?来,让我们挨个看一下这几个绑定类在调用initInstances()的时候做了什么的吧。

第一个是GestureBinding。手势绑定。

mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, HitTestTarget {
@override
void initInstances() {
super.initInstances();
_instance = this;
window.onPointerDataPacket = _handlePointerDataPacket;
}

在调用initInstances()的时候,主要做的事情就是给window设置了一个手势处理的回调函数。所以这个绑定主要是负责管理手势事件的。

第二个是ServicesBinding。服务绑定

mixin ServicesBinding on BindingBase {
@override
void initInstances() {
super.initInstances();
_instance = this;
window
…onPlatformMessage = BinaryMessages.handlePlatformMessage;
initLicenses();
}

这个绑定主要是给window设置了处理Platform Message的回调。

第三个是SchedulerBinding。调度绑定。

mixin SchedulerBinding on BindingBase, ServicesBinding {
@override
void initInstances() {
super.initInstances();
_instance = this;
window.onBeginFrame = _handleBeginFrame;
window.onDrawFrame = _handleDrawFrame;
SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
}

这个绑定主要是给window设置了onBeginFrameonDrawFrame的回调,回忆一下上一篇文章讲渲染流水线的时候,当Vsync信号到来的时候engine会回调Flutter的来启动渲染流程,这两个回调就是在SchedulerBinding管理的。

第四个是PaintingBinding。绘制绑定。

mixin PaintingBinding on BindingBase, ServicesBinding {
@override
void initInstances() {
super.initInstances();
_instance = this;
_imageCache = createImageCache();
}

这个绑定只是创建了个图片缓存,就不细说了。

第五个是SemanticsBinding。辅助功能绑定。

mixin SemanticsBinding on BindingBase {
@override
void initInstances() {
super.initInstances();
_instance = this;
_accessibilityFeatures = window.accessibilityFeatures;
}

这个绑定管理辅助功能,就不细说了。

第六个是RendererBinding。渲染绑定。这是比较重要的一个类。

mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, HitTestable {
@override
void initInstances() {
super.initInstances();
_instance = this;
_pipelineOwner = PipelineOwner(
onNeedVisualUpdate: ensureVisualUpdate,
onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
);
window
…onMetricsChanged = handleMetricsChanged
…onTextScaleFactorChanged = handleTextScaleFactorChanged
…onPlatformBrightnessChanged = handlePlatformBrightnessChanged
…onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
…onSemanticsAction = _handleSemanticsAction;
initRenderView();
_handleSemanticsEnabledChanged();
assert(renderView != null);
addPersistentFrameCallback(_handlePersistentFrameCallback);
_mouseTracker = _createMouseTracker();
}

这个绑定是负责管理渲染流程的,初始化的时候做的事情也比较多。 首先是实例化了一个PipelineOwner类。这个类负责管理驱动我们之前说的渲染流水线。随后给window设置了一系列回调函数,处理屏幕尺寸变化,亮度变化等。接着调用initRenderView()

void initRenderView() {
assert(renderView == null);
renderView = RenderView(configuration: createViewConfiguration(), window: window);
renderView.scheduleInitialFrame();
}

这个函数实例化了一个RenderView类。RenderView继承自RenderObject。我们都知道Flutter框架中存在这一个渲染树(render tree)。这个RenderView就是渲染树(render tree)的根节点,这一点可以通过打开"Flutter Inspector"看到,在"Render Tree"这个Tab下,最根部的红框里就是这个RenderView

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后调用addPersistentFrameCallback添加了一个回调函数。请大家记住这个回调,渲染流水线的主要阶段都会在这个回调里启动。

第七个是WidgetsBinding,组件绑定。

mixin WidgetsBinding on BindingBase, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
@override
void initInstances() {
super.initInstances();
_instance = this;
buildOwner.onBuildScheduled = _handleBuildScheduled;
window.onLocaleChanged = handleLocaleChanged;
window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged;
SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);
SystemChannels.system.setMessageHandler(_handleSystemMessage);
}

这个绑定的初始化先给buildOwner设置了个onBuildScheduled回调,还记得渲染绑定里初始化的时候实例化了一个PipelineOwner吗?这个BuildOwner是在组件绑定里实例化的。它主要负责管理Widget的重建,记住这两个"owner"。他们将会Flutter框架里的核心类。接着给window设置了两个回调,因为和渲染关系不大,就不细说了。最后设置SystemChannels.navigationSystemChannels.system的消息处理函数。这两个回调一个是专门处理路由的,另一个是处理一些系统事件,比如剪贴板,震动反馈,系统音效等等。

至此,WidgetsFlutterBinding.ensureInitialized()就跑完了,总体上来讲是把window提供的API分别封装到不同的Binding里。我们需要重点关注的是SchedulerBindingRendererBindingWidgetsBinding。这3个是渲染流水线的重要存在。

接下来就该看一下runApp()里的第二个调用了。

attachRootWidget(app)

这个函数的代码如下:

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

在之前说的RendererBinding的初始化的时候,我们得到了一个RenderView的实例,render tree的根节点。RenderView是继承自RenderObject的,而RenderObject需要有对应的WidgetElement。上述代码中的RenderObjectToWidgetAdapter就是这个Widget。而对应的Element就是RenderObjectToWidgetElement了,既然是要关联到render tree的根节点,那它自然也就是element tree的根节点了。

从上述分析我们可以得出结论:

  • 渲染绑定(RendererBinding)通过pipelineOwner间接持有render tree的根节点RenderView
  • 组件绑定(WidgetsBinding)持有element tree的根节点RenderObjectToWidgetElement

那么RenderObjectToWidgetElement是怎么和RenderView关联起来的呢,那自然是通过一个Widget做到的了,看下RenderObjectToWidgetAdapter的代码:

class RenderObjectToWidgetAdapter extends RenderObjectWidget {
/// Creates a bridge from a [RenderObject] to an [Element] tree.
///
/// Used by [WidgetsBinding] to attach the root widget to the [RenderView].
RenderObjectToWidgetAdapter({
this.child,
this.container,
this.debugShortDescription
}) : super(key: GlobalObjectKey(container));

@override
RenderObjectToWidgetElement createElement() => RenderObjectToWidgetElement(this);

@override
RenderObjectWithChildMixin createRenderObject(BuildContext context) => container;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

那我们该怎么做才能做到年薪60万+呢,对于程序员来说,只有不断学习,不断提升自己的实力。我之前有篇文章提到过,感兴趣的可以看看,到底要学习哪些知识才能达到年薪60万+。

通过职友集数据可以查看,以北京 Android 相关岗位为例,其中 【20k-30k】 薪酬的 Android 工程师,占到了整体从业者的 30.8%!

北京 Android 工程师「工资收入水平 」

今天重点内容是怎么去学,怎么提高自己的技术。

1.合理安排时间

2.找对好的系统的学习资料

3.有老师带,可以随时解决问题

4.有明确的学习路线

当然图中有什么需要补充的或者是需要改善的,可以在评论区写下来,一起交流学习。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

理安排时间

2.找对好的系统的学习资料

3.有老师带,可以随时解决问题

4.有明确的学习路线

当然图中有什么需要补充的或者是需要改善的,可以在评论区写下来,一起交流学习。

[外链图片转存中…(img-WN6OE4Vh-1712271271884)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 23
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值