PipelineManifold
PipelineManifold 用于管理一棵 PipelineOwner Tree。
PipelineOwner Tree 中的所有 PipelineOwner 都附加到同一个 PipelineManifold 对象,这使的所有的 PipelineOwner 对象能够访问共享功能,例如请求视觉更新(通过调用 manifold.requestVisualUpdate())。因此,PipelineManifold 为 PipelineOwners 提供了通常由 bindings 提供的功能,而不将 PipelineOwners 绑定到特定的 binding 实现。
PipelineOwner Tree 的根通过将 PipelineManifold 传递给 PipelineOwner.attach 与 PipelineManifold 相连。当通过 PipelineOwner.adoptChild 收养子级 PipelineOwner 时,子级将附加到与其父级相同的 PipelineManifold 对象。
PipelineOwners 可以在 PipelineManifold 中注册监听器,以在 PipelineManifold 提供的某些值更改时得到通知。
Constructors
PipelineManifold 是一个需要实现 Listenable 接口的抽象类。即交由它的子类来实现了。(下一篇我们会着重分析 Listenable 和 ChangeNotifier 提供的 发布-订阅 机制。)
abstract class PipelineManifold implements Listenable {
// ...
}
semanticsEnabled
PipelineOwners 连接到此 PipelineManifold 是否应收集语义信息并生成语义树。
当此属性更改其值时,PipelineManifold 会通知其监听器(通过 addListener 和 removeListener 管理)。
另请参阅:
- SemanticsBinding.semanticsEnabled,PipelineManifold 实现通常用来支持此属性。
bool get semanticsEnabled;
requestVisualUpdate
当与此 PipelineManifold 连接的 PipelineOwner 调用时,用于更新与该 PipelineOwner 关联的 RenderObject 对象的视觉外观(即执行 flush 系列函数)。
通常,此函数的实现会安排任务(即回调 RendererBinding.drawFrame 函数)来刷新管道的各个阶段(即执行 flush 系列函数)。此函数可能会被快速连续地调用多次。实现应该小心地快速丢弃重复调用。(可能会被多处调用,调用过于频繁,但是仅需要在下一帧统一处理那些 flush 请求即可,例如:在 Render Tree 构建过程中每个节点都会调用此函数,请求进行视觉更新。)
与此 PipelineManifold 连接的 PipelineOwner 如果已配置使用非空的 PipelineOwner.onNeedVisualUpdate 回调(看到 RendererBinding 的 rootPipelineOwner 的 onNeedVisualUpdate 是没有配置的,所以请求刷新时,还是用这个方法比较靠谱。),将调用 PipelineOwner.onNeedVisualUpdate 而不是调用此方法。
另请参阅:
- SchedulerBinding.ensureVisualUpdate,通常由 PipelineManifold 实现调用以实现此方法。
void requestVisualUpdate();
PipelineManifold 总结
其实直白一点理解 PipelineManifold,它就是一个中间层。所有的 PipelineOwner 都指向它,也即是所有的 PipelineOwner 都可以直接访问它,也即是 PipelineOwner 中收集的所有脏 RenderObject 对象都可以访问它(调用它的函数)。
当它们 PipelineOwner 想要刷新时,如在 RenderObject 需要 Layout/Paint/CompositedLayerUpdate/SemanticsUpdate/InitialSemantics 时调了五次的 owner!.requestVisualUpdate();,此时发出的 requestVisualUpdate 请求都交给了它们的 PipelineManifold? _manifold 属性:_manifold?.requestVisualUpdate();。那么它们的 PipelineManifold? _manifold 属性置在哪里呢?其实有一个全局的 PipelineManifold 默认值。
在 RendererBinding 中提供了一个 late final PipelineManifold _manifold = _BindingPipelineManifold(this); 变量,_BindingPipelineManifold 是 PipelineManifold 的直接子类,所以此 _manifold 是一个全局的 PipelineManifold 变量,而它呢在 RendererBinding.initInstances 函数内直接通过:rootPipelineOwner.attach(_manifold); 附加到了 PipelineOwner Tree 的根节点。
然后当所有的 PipelineOwner 发出 requestVisualUpdate 请求时,都到了 RendererBinding._manifold 这里,而在 _BindingPipelineManifold 类内部,它的 requestVisualUpdate 函数则是直接调用 RendererBinding 这个 binding 的 ensureVisualUpdate 函数调度新的一帧生成。
所以最后兜兜转转,通过 PipelineManifold 这个中间层,还是把任务交到了 RendererBinding 手中。
下面我们看一下目前全局唯一的一个 PipelineManifold 子类:_BindingPipelineManifold 的内容。
_BindingPipelineManifold
在 RendererBinding Mixin 中第一个属性是它的单例属性 instance,第二个属性便是:late final PipelineManifold _manifold = _BindingPipelineManifold(this);,可见 manifold 的重要性,并且我们看到 _BindingPipelineManifold 构造函数是直接把当前的 binding 传进去了,是的没错:_manifold 会直接引用这个 RendererBinding.instance。
Constructors
构造函数需要传入一个 binding。然后它继承 ChangeNotifier,以满足 Listenable 接口的要求。
class _BindingPipelineManifold extends ChangeNotifier implements PipelineManifold {
_BindingPipelineManifold(this._binding) {
// 添加 semanticsEnabled 值发生变化的监听,当发生变化时,
// 会回调 PipelineOwner 的 _updateSemanticsOwner 函数。
_binding.addSemanticsEnabledListener(notifyListeners);
}
// ...
}
_binding
最重要的属性,_BindingPipelineManifold 类完成的最重要的两个功能,其实都是由此 binding 来实现的。
final RendererBinding _binding;
requestVisualUpdate
请求视觉刷新,在 PipelineOwner 的刷新阶段中都要调用它。
@override
void requestVisualUpdate() {
_binding.ensureVisualUpdate();
}
semanticsEnabled
当前 semanticsEnabled 的值,开或者关。
@override
bool get semanticsEnabled => _binding.semanticsEnabled;
dispose
当销毁时需要移除监听。
@override
void dispose() {
// 移除监听。
_binding.removeSemanticsEnabledListener(notifyListeners);
super.dispose();
}
_BindingPipelineManifold 总结
一个超简单的类,大概作为了 Binding 与我们的 RenderObject 对象之间的中间层。特别是对 RenderObject 而言超级重要的请求视觉更新,是通过它传递到了 Binding 中,再传递到 Flutter engine。
然后另外一个是当 SemanticsBinding.semanticsEnabled 值变化时,通知到 PipelineOwner 中进行 _updateSemanticsOwner 回调,根据开或者关,创建或者销毁 SemanticsOwner,即回调到 PipelineOwner 里是否处理与语义化相关的内容。
内容都比较简单,快速浏览即可,但是还是有必要看一下,不断加深对 Binding 的理解,继而掌握 Flutter 整个框架。
参考链接
参考链接:🔗