Flutter 中的 Binding

半亩方塘一鉴开,天光云影共徘徊。
问渠那得清如许?为有源头活水来。

上面这首诗出自宋代朱熹的《观书有感》,其中“问渠那得清如许?为有源头活水来。”经常被我们引用,用来表示想要心灵澄清,就得认真读书,试试补充新知识。

但我们这里的主题是 Flutter,它和这两句诗有什么关系呢?

一、BindingBase

在 Flutter 中有一个叫做 BindingBase 的类,作为一个抽象类,它为 Flutter 上层提供了源源不断的活水。那么接下来就让我们好好了解一下这个 BindingBase。

Base class for mixins that provide singleton services (also known as “bindings”).

To use this class in a mixin, inherit from it and implement initInstances(). The mixin is guaranteed to only be constructed once in the lifetime of the app (more precisely, it will assert if constructed twice in checked mode).

The top-most layer used to write the application will have a concrete class that inherits from BindingBase and uses all the various BindingBase mixins (such as ServicesBinding). For example, the Widgets library in Flutter introduces a binding called WidgetsFlutterBinding. The relevant library defines how to create the binding. It could be implied (for example, WidgetsFlutterBinding is automatically started from runApp), or the application might be required to explicitly call the constructor.

看一下官方的说明,大概就是说 BindingBase 是作为提供单例服务的 mixins 的基类。这里说到了 mixins 可能有些小伙伴不是很熟悉,我在下一段做下说明。接下来说的都是一些 BindingBase 的使用方法,我们主要是学习它,除非你要重写一套 Flutter 框架,否则几乎不用自己去继承和实现 BindingBase 的子类。接着看 BindingBase 中的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
abstract class BindingBase {
/**
* 默认的构造函数,用于调用 initInstances 和 initServiceExtensions 方法
**/

BindingBase() {
...
}
/**
* 用于子类重写该方法,在该方法中对 flutter 底层进行 hook 操作。
**/

void initInstances() {
...
}
/**
* 用于子类重写该方法,用于注册一些扩展服务。
* 具体可以参考:https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#rpcs-requests-and-responses
**/

void initServiceExtensions() {
...
}

Future<Null> lockEvents(Future<Null> callback()) {
...
}

void unlocked() {
...
}
/**
* 开发工具通过此方法让 App 进行重绘操作,一般发生在代码发生修改时。
**/

Future<Null> reassembleApplication() {
...
}
/**
* 被 reassembleApplication 方法调用,用于真正实现应用重绘。
**/

Future<Null> performReassemble() {
FlutterError.resetErrorCount();
return new Future<Null>.value();
}
/**
* 注册相关扩展服务
**/

void registerSignalServiceExtension({
@required String name,
@required AsyncCallback callback
}) {
...
}
/**
* 注册相关扩展服务
**/

void registerBoolServiceExtension({
@required String name,
@required AsyncValueGetter<bool> getter,
@required AsyncValueSetter<bool> setter
}) {
...
}
/**
* 注册相关扩展服务
**/

void registerNumericServiceExtension({
@required String name,
@required AsyncValueGetter<double> getter,
@required AsyncValueSetter<double> setter
}) {
...
}
/**
* 注册相关扩展服务
**/

void registerStringServiceExtension({
@required String name,
@required AsyncValueGetter<String> getter,
@required AsyncValueSetter<String> setter
}) {
...
}
/**
* 注册相关扩展服务
**/

void registerServiceExtension({
@required String name,
@required ServiceExtensionCallback callback
}) {
...
}

@override
String toString() => '<$runtimeType>';
}

BindingBase 的方法并不多,一些重要方法的说明我写在了方法上方。总体上 BindingBase 并不复杂它主要就是用来初始化一些与底层交互的服务。

二、Mixins

在讲 Flutter 中众多的 Binding 前,有必要先简单讲一讲 Mixins 这一语法特性,它最早应该出现在 LISP 中,用于实现多继承相关的操作。具体想要了解可以参考此处

下面我介绍一下 Dart 中 Mixins 的一些相关概念:

  1. 每一个类都隐式地定义了一个 mixin,此 mixin 的内容即为该类的主体。
  2. 每一个类都是一个 mixin application,是由该类隐式定义的 mixin 应用到其父类后产生的。
  3. 如 M 是一个 mixin,则 M 可以被看做是一个方法,此方法的输入 S 为父类,则输出 C 为子类。C 也称作 mixin application。写作 C = M |> S。
  4. S 中的私有成员可以在其生成的 mixin application 中进行访问。
  5. S 中的静态成员无法在其生成的 mixin application 中访问。
  6. 由于C 既可以看做是 S 的子类,也能看做 M 的子类,所以在 C = M |> S 中,C 必须要实现 M 父类的所有接口,以此保证 C 是 M 子类成立。

接着看一个简单的例子:

1
2
3
4
5
6
7
8
9
abstract class Calabash{
Calabash(){
init();
}

init(){
print('我是葫芦娃!');
}
}

上面是一个葫芦娃的抽象类,虽然没有继承任何类但是它有默认的父类 Object。所以根据上面提到的 1、2 、3 两点,可以理解 Calabash 隐式定义了一个 mixin,它的内容为其 class 部分的代码。而 Calabash 则是此 mixin 应用在 Object 上的结果。

接着看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
class RedCalabash extends Calabash{

@override
init() {
super.init();
print("我是红娃!");
}

strong() {
print("我力大无穷!");
}
}

class OrangeCalabash extends Calabash{

@override
init() {
super.init();
print("我是橙娃!");
}

eyeAndEar() {
print("我是千里眼顺风耳!");
}
}

class YellowCalabash extends Calabash{

@override
init() {
super.init();
print("我是黄娃!");
}

hardBody() {
print("我铜头铁臂,刀枪不入");
}
}
class GreenCalabash extends Calabash{

@override
init() {
super.init();
print("我是绿娃!");
}

fire() {
print("我能吸火吐火!");
}
}

class CyanCalabash extends Calabash{

@override
init() {
super.init();
print("我是青娃!");
}

water() {
print("我能吸水吐水!");
}
}

class BlueCalabash extends Calabash{

@override
init() {
super.init();
print("我是蓝娃!");
}

transparency() {
print("我能隐身!");
}
}
class PurpleCalabash extends Calabash{

@override
init() {
super.init();
print("我是紫娃!");
}

calabash() {
print("我有宝葫芦!");
}
}

我另外定义了七个类 RedCalabash、OrangeCalabash、YellowCalabash、GreenCalabash、CyanCalabash、BlueCalabash、PurpleCalabash 它们都继承了 Calabash 并重写了 init 方法。注意到其中的 init 中调用了 super.init() 方法。同理可以理解上面七个类也隐式地定义了七个 mixin,它们分别表示了七个葫芦娃不同于抽象类 Calabash 的部分。

接着看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

class KingKongCalabash extends Calabash with PurpleCalabash,BlueCalabash,CyanCalabash,GreenCalabash,YellowCalabash,OrangeCalabash,RedCalabash{


@override
init() {
super.init();
print("我是葫芦小金刚!");
}

ability() {
strong();
eyeAndEar();
hardBody();
fire();
water();
transparency();
calabash();
}
}

main(){
var kingKongCalabash = new KingKongCalabash();
kingKongCalabash.ability();
}

我定义了一个名为 KingKongCalabash 的类,大家可能都会先入为主觉得它的父类是 Calabash,但其实不然,extends 的优先级低于 with,所以首先要计算 with 部分。其顺序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
(
(
(
(
(
(
Calabash with PurpleCalabash
) with BlueCalabash
) with CyanCalabash
) with GreenCalabash
) with YellowCalabash
) with OrangeCalabash
) with RedCalabash

虽然上面的代码不是很美观,但可以比较直观的看出最后使用的是 RedCalabash 这个 mixin,所以 KingKongCalabash 实际上继承的是应用了七个 mixin 的类,这有点类似多继承。

接着运行 main 方法,结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
我是葫芦娃!
我是紫娃!
我是蓝娃!
我是青娃!
我是绿娃!
我是黄娃!
我是橙娃!
我是红娃!
我是葫芦小金刚!
我力大无穷!
我是千里眼顺风耳!
我铜头铁臂,刀枪不入
我能吸火吐火!
我能吸水吐水!
我能隐身!
我有宝葫芦!

Process finished with exit code 0

其输出顺序正好是 mixin 的顺序。

接着说上面的第 6 点,为什么 C 必须要实现 M 父类中的所有方法?放到葫芦娃的例子就是 KingKongCalabash 必须要实现 RedCalabash、OrangeCalabash、YellowCalabash、GreenCalabash、CyanCalabash、BlueCalabash、PurpleCalabash 这七个类的父类 。由于这里他们的父类都是 Calabash,所以 KingKongCalabash 只要也继承 Calabash 那默认也就实现了所有的接口。想象一下,如果 Calabash 中有一个方法为 foo,而这个方法在 RedCalabash 中调用了,然后 KingKongCalabash 继承的不是 Calabash,而是一个没有 foo 方法的类,那么结果会怎么样?大家可以自己试试。

以上就是 dart 中关于 mixin 的简单介绍,接下来我们进入 Binding 的世界。

三、Binding

在第一节介绍了 BindingBase 这个类,以下是示意图:

BindingBase 就像是第三节中的 Calabash,给所有的 Binding 提供了一个基础。类似的这里有 GestureBinding、ServicesBinding、SchedulerBinding、PaintingBinding、RendererBinding、WidgetsBinding 和 WidgetsFlutterBinding 这七个 Binding,我们一个一个的看。

1. GestureBinding

GestureBinding 的介绍很简单,一句话:

1
2
> A binding for the gesture subsystem.
>

意思就是和手势系统进行绑定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
abstract class GestureBinding extends BindingBase with HitTestable, HitTestDispatcher, HitTestTarget {

factory GestureBinding._() => null;

@override
void initInstances() {
...
}

@override
void unlocked() {
super.unlocked();
_flushPointerEventQueue();
}

static GestureBinding get instance => _instance;
static GestureBinding _instance;

final Queue<PointerEvent> _pendingPointerEvents = new Queue<PointerEvent>();

void _handlePointerDataPacket(ui.PointerDataPacket packet) {
...
}

/// 取消点事件
void cancelPointer(int pointer) {
...
}

void _flushPointerEventQueue() {
assert(!locked);
while (_pendingPointerEvents.isNotEmpty)
_handlePointerEvent(_pendingPointerEvents.removeFirst());
}

/// 点事件的路由
final PointerRouter pointerRouter = new PointerRouter();

/// 手势识别器管理
final GestureArenaManager gestureArena = new GestureArenaManager();

final Map<int, HitTestResult> _hitTests = <int, HitTestResult>{};

/// 处理点事件
void _handlePointerEvent(PointerEvent event) {
...
}

void hitTest(HitTestResult result, Offset position) {
...
}

void dispatchEvent(PointerEvent event, HitTestResult result) {
...
}

void handleEvent(PointerEvent event, HitTestEntry entry) {
...
}
}

以上就是 GestureBinding 的部分方法与说明,简单说,GestureBinding 就是从 Flutter 的引擎 sky 中获取点事件,然后将点事件转换成手势事件。而它的三个 mixin 均与命中测试有关,命中测试并不是本次讨论的重点,感兴趣的小伙伴可自行研究。下面是 GestureBinding 的示意图:

2. ServicesBinding

ServiceBinding 介绍如下:

Listens for platform messages and directs them to BinaryMessages.

The ServicesBinding also registers a LicenseEntryCollector that exposes the licenses found in the LICENSE file stored at the root of the asset bundle, and implements the ext.flutter.evict service extension (see evict).

简单说 ServicesBinding 负责将 flutter 引擎的 message 转发给 BinaryMessages 进行处理。另外它也提供了 LICENSE 文件的相关功能和图片缓存的清理功能。

此处的 message 一般用于插件开发中平台与 Flutter 进行通信。由于 ServicesBinding 相对简单,代码就不贴了。下面是 ServiceBinding 的示意图:

3. SchedulerBinding

SchedulerBinding 介绍如下:

Scheduler for running the following:

  • Transient callbacks, triggered by the system’s Window.onBeginFrame callback, for synchronizing the application’s behavior to the system’s display. For example, Tickers and AnimationControllers trigger from these.
  • Persistent callbacks, triggered by the system’s Window.onDrawFrame callback, for updating the system’s display after transient callbacks have executed. For example, the rendering layer uses this to drive its rendering pipeline.
  • Post-frame callbacks, which are run after persistent callbacks, just before returning from the Window.onDrawFrame callback.
  • Non-rendering tasks, to be run between frames. These are given a priority and are executed in priority order according to a schedulingStrategy.

简单讲 SchedulerBinding 是专门用来执行以上四种回调或任务的。其中与上册联系最紧密的就是 Transient callbacks,它主要负责对 Flutter 中动画的驱动。Persistent callbacks 负责渲染管线的驱动。Post-frame callbacks 则是在 persistent callbacks 后在 Window.onDrawFrame callback 之前调用,具体作用目前不详,以后涉及到再说。最后一个 Non-rendering tasks 则是在每两帧之间被调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
abstract class SchedulerBinding extends BindingBase with ServicesBinding {
factory SchedulerBinding._() => null;

@override
void initInstances() {
super.initInstances();
_instance = this;
ui.window.onBeginFrame = _handleBeginFrame; //注册帧前回调
ui.window.onDrawFrame = _handleDrawFrame; //注册帧内回调
SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
}

static SchedulerBinding get instance => _instance;
static SchedulerBinding _instance;

@override
void initServiceExtensions() {
...
}

AppLifecycleState get lifecycleState => _lifecycleState;
/// 应用生命周期状态
AppLifecycleState _lifecycleState;


/// 生命周期改变后的处理
void handleAppLifecycleStateChanged(AppLifecycleState state) {
...
}

Future<String> _handleLifecycleMessage(String message) {
...
}

static AppLifecycleState _parseAppLifecycleMessage(String message) {
...
}

SchedulingStrategy schedulingStrategy = defaultSchedulingStrategy;

static int _taskSorter (_TaskEntry e1, _TaskEntry e2) {
...
}
final PriorityQueue<_TaskEntry> _taskQueue = new HeapPriorityQueue<_TaskEntry>(_taskSorter);

void scheduleTask(VoidCallback task, Priority priority) {
...
}

void unlocked() {
...
}

bool _hasRequestedAnEventLoopCallback = false;

void _ensureEventLoopCallback() {
...
}

void _runTasks() {
...
}

bool handleEventLoopCallback() {
...
}

int _nextFrameCallbackId = 0; // positive
Map<int, _FrameCallbackEntry> _transientCallbacks = <int, _FrameCallbackEntry>{};
final Set<int> _removedIds = new HashSet<int>();


int get transientCallbackCount => _transientCallbacks.length;

///动画相关,详细内容大伙自行学习
int scheduleFrameCallback(FrameCallback callback, { bool rescheduling: false }) {
...
}

void cancelFrameCallbackWithId(int id) {
...
}

bool debugAssertNoTransientCallbacks(String reason) {
...
}

static void debugPrintTransientCallbackRegistrationStack() {
...
}

final List<FrameCallback> _persistentCallbacks = <FrameCallback>[];

void addPersistentFrameCallback(FrameCallback callback) {
...
}

final List<FrameCallback> _postFrameCallbacks = <FrameCallback>[];

void addPostFrameCallback(FrameCallback callback) {
...
}

Completer<Null> _nextFrameCompleter;

Future<Null> get endOfFrame {
...
}

bool get hasScheduledFrame => _hasScheduledFrame;
bool _hasScheduledFrame = false;

SchedulerPhase get schedulerPhase => _schedulerPhase;
SchedulerPhase _schedulerPhase = SchedulerPhase.idle;

bool get framesEnabled => _framesEnabled;

bool _framesEnabled = true;
void _setFramesEnabledState(bool enabled) {
...
}

void ensureVisualUpdate() {
...
}

///用于提示底层引擎开始刷新下一帧
void scheduleFrame() {
...
}

void scheduleForcedFrame() {
...
}

bool _warmUpFrame = false;

void scheduleWarmUpFrame() {
...
}

Duration _firstRawTimeStampInEpoch;
Duration _epochStart = Duration.ZERO;
Duration _lastRawTimeStamp = Duration.ZERO;

void resetEpoch() {
...
}

Duration _adjustForEpoch(Duration rawTimeStamp) {
...
}

Duration get currentFrameTimeStamp {
...
}
Duration _currentFrameTimeStamp;

int _profileFrameNumber = 0;
final Stopwatch _profileFrameStopwatch = new Stopwatch();
String _debugBanner;
bool _ignoreNextEngineDrawFrame = false;

void _handleBeginFrame(Duration rawTimeStamp) {
...
}

void _handleDrawFrame() {
...
}

/// 帧前回调处理
void handleBeginFrame(Duration rawTimeStamp) {
...
}

/// 底层引擎的回调,用于生成新的一帧
void handleDrawFrame() {
...
}

void _profileFramePostEvent() {
...
}

static void _debugDescribeTimeStamp(Duration timeStamp, StringBuffer buffer) {
...
}

void _invokeFrameCallback(FrameCallback callback, Duration timeStamp, [ StackTrace callbackStack ]) {
...
}

SchedulerBinding 的代码还是比较多且复杂的,但想要找帧之间回调相关的内容来 SchedulerBinding 就对了。SchedulerBinding 的示意图如下:

4. PaintingBinding

PaintingBinding 的说明如下:

Binding for the painting library.

Hooks into the cache eviction logic to clear the image cache.

Requires the ServicesBinding to be mixed in earlier.

看到 Painting 可能会觉得它和帧的绘制有关,但事实上它跟帧绘制没有一点关系,它目前只是用来做图像缓存管理。由于代码很简短,这里也不贴了。PaintingBinding 示意图如下:

5. RendererBinding

RendererBinding 介绍如下:

The glue between the render tree and the Flutter engine.

官方介绍真是简洁明了,RendererBinding 是底层引擎和渲染树之间的连接。这里出现了渲染树这个概念,渲染树只是 Flutter Framework 中众多树中的一棵,它是由名为 RenderObject 的渲染对象形成,用于实现 Flutter 的帧绘制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
abstract class RendererBinding extends BindingBase with ServicesBinding, SchedulerBinding, HitTestable {
factory RendererBinding._() => null;

@override
void initInstances() {
...
}

static RendererBinding get instance => _instance;
static RendererBinding _instance;

@override
void initServiceExtensions() {
...
}

/// 初始化 RenderView,注意此处的 RenderView 为渲染树的根节点,在以后介绍渲染树会做详细讲解
void initRenderView() {
...
}

/// PipelineOwner 负责管理渲染管线
PipelineOwner get pipelineOwner => _pipelineOwner;
PipelineOwner _pipelineOwner;

RenderView get renderView => _pipelineOwner.rootNode;
...
}

void handleMetricsChanged() {
...
}

void handleTextScaleFactorChanged() { }

/// 屏幕相关配置
ViewConfiguration createViewConfiguration() {
...
}

SemanticsHandle _semanticsHandle;

void _handleSemanticsEnabledChanged() {
setSemanticsEnabled(ui.window.semanticsEnabled);
}

void setSemanticsEnabled(bool enabled) {
...
}

void _handleSemanticsOwnerCreated() {
...
}

void _handleSemanticsOwnerDisposed() {
...
}

void _handlePersistentFrameCallback(Duration timeStamp) {
...
}

/// 绘制帧
void drawFrame() {
...
}

@override
Future<Null> performReassemble() async {
...
}

@override
void hitTest(HitTestResult result, Offset position) {
...
}

Future<Null> _forceRepaint() {
...
}
}

RendererBinding 内部比较负责并且涉及到了管线部分的内容,这里不做过多介绍。大家只要知道想找帧绘制相关的内容来 RendererBinding 就对了。下面是 RendererBinding 的示意图:

6. WidgetsBinding

WidgetsBinding 是这次 Binding 中的重点介绍对象,先看下它的示意图:

可以看到它把前面讲到的 GestureBinding、ServicesBinding、SchedulerBinding、PaintingBinding、RendererBinding 都囊括了进来,也就是说在 WidgetsBinding 中可以访问以上 Binding 的所有功能。

WidgetsBinding 的介绍如下:

The glue between the widgets layer and the Flutter engine.

意思是说 WidgetsBinding 是 Flutter 引擎和控件层之间的连接。说到控件层,这里要介绍一下Flutter 中的第二棵树控件树。它负责组织 Flutter App 中的所有控件。另外控件也是我们在编写 Flutter App 时直接接触的对象。比如一个 MaterialApp 的基本树结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
abstract class WidgetsBinding extends BindingBase with SchedulerBinding, GestureBinding, RendererBinding {
factory WidgetsBinding._() => null;

@override
void initInstances() {
...
}

static WidgetsBinding get instance => _instance;
static WidgetsBinding _instance;

@override
void initServiceExtensions() {
...
}

Future<Null> _forceRebuild() {
...
}

/// 控件树的管理者
BuildOwner get buildOwner => _buildOwner;
final BuildOwner _buildOwner = new BuildOwner();

FocusManager get focusManager => _buildOwner.focusManager;

final List<WidgetsBindingObserver> _observers = <WidgetsBindingObserver>[];

void addObserver(WidgetsBindingObserver observer) => _observers.add(observer);

bool removeObserver(WidgetsBindingObserver observer) => _observers.remove(observer);

@override
void handleMetricsChanged() {
...
}

@override
void handleTextScaleFactorChanged() {
...
}

void handleLocaleChanged() {
...
}

void dispatchLocaleChanged(Locale locale) {
...
}

Future<Null> handlePopRoute() async {
...
}

Future<Null> handlePushRoute(String route) async {
...
}

Future<dynamic> _handleNavigationInvocation(MethodCall methodCall) {
...
}

@override
void handleAppLifecycleStateChanged(AppLifecycleState state) {
...
}

void handleMemoryPressure() {
...
}

Future<dynamic> _handleSystemMessage(Map<String, dynamic> message) async {
...
}

bool _needToReportFirstFrame = true;
int _deferFirstFrameReportCount = 0;
bool get _reportFirstFrame => _deferFirstFrameReportCount == 0;

void deferFirstFrameReport() {
...
}

void allowFirstFrameReport() {
...
}

void _handleBuildScheduled() {
...
}

bool debugBuildingDirtyElements = false;

/// 帧绘制相关,内部调用 RendererBinding 相关方法
void drawFrame() {
...
}

/// Flutter 中的第三棵树元素树的根节点
Element get renderViewElement => _renderViewElement;
Element _renderViewElement;

/// 此处的 rootWidget 就是我们传递给 runApp 的 Widget。
/// 这里是将 rootWidget 与 RenderView 和 RenderViewElement 相关联。
void attachRootWidget(Widget rootWidget) {
_renderViewElement = new RenderObjectToWidgetAdapter<RenderBox>(
container: renderView,
debugShortDescription: '[root]',
child: rootWidget
).attachToRenderTree(buildOwner, renderViewElement);
}

Future<Null> performReassemble() {
...
}
}

上面就是 WidgetsBinding 类的简单介绍,用一句话概括的话就是 WidgetsBinding 集合了所有 Binding 的功能,并将 Widgets 树、RenderObject 树和 Elements 关联在一起。

WidgetsBinding 将这些方方面面整合在一起,保证了 Flutter App 所需的一切。

7. WidgetsFlutterBinding

最后要说下 WidgetsFlutterBinding,它是 WidgetsFlutter 的子类,其本身没多大作用,它做的就是将前面的这些 Binding 作为 mixin 应用在 BindingBase 上。其本身只提供了如下一个方法:

1
2
3
4
5
6
/// 实例化 WidgetsBinding
static WidgetsBinding ensureInitialized() {
if (WidgetsBinding.instance == null)
new WidgetsFlutterBinding();
return WidgetsBinding.instance;
}

最后来看下这七个 Binding 的大合照:

看大图请点击此处

四、总结

我们所写的 Flutter app 之所以可以在屏幕上显示并响应我们的手势操作,靠的就是这个七个 Binding 帮我们抽象了 Flutter 引擎的底层接口,并提供更为简洁的上层接口。想要学习 Flutter 框架的话这七个 Binding 是很好的学习入口。

如文章对您有所帮助,可以请作者喝杯 🍵