混入的那些各种绑定类也都是继承自抽象类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
设置了onBeginFrame
和onDrawFrame
的回调,回忆一下上一篇文章讲渲染流水线的时候,当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.navigation
和SystemChannels.system
的消息处理函数。这两个回调一个是专门处理路由的,另一个是处理一些系统事件,比如剪贴板,震动反馈,系统音效等等。
至此,WidgetsFlutterBinding.ensureInitialized()
就跑完了,总体上来讲是把window
提供的API分别封装到不同的Binding里。我们需要重点关注的是SchedulerBinding
,RendererBinding
和WidgetsBinding
。这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
需要有对应的Widget
和Element
。上述代码中的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移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://i-blog.csdnimg.cn/blog_migrate/bc24b789d3171048ff0527c4a7542523.jpeg)
最后
那我们该怎么做才能做到年薪60万+呢,对于程序员来说,只有不断学习,不断提升自己的实力。我之前有篇文章提到过,感兴趣的可以看看,到底要学习哪些知识才能达到年薪60万+。
通过职友集数据可以查看,以北京 Android 相关岗位为例,其中 【20k-30k】 薪酬的 Android 工程师,占到了整体从业者的 30.8%!
北京 Android 工程师「工资收入水平 」
今天重点内容是怎么去学,怎么提高自己的技术。
1.合理安排时间
2.找对好的系统的学习资料
3.有老师带,可以随时解决问题
4.有明确的学习路线
当然图中有什么需要补充的或者是需要改善的,可以在评论区写下来,一起交流学习。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
理安排时间
2.找对好的系统的学习资料
3.有老师带,可以随时解决问题
4.有明确的学习路线
当然图中有什么需要补充的或者是需要改善的,可以在评论区写下来,一起交流学习。
[外链图片转存中…(img-WN6OE4Vh-1712271271884)]