flutter_boost如何接管Navigator
以下分析基于 flutter_boost 分支 feature/flutter_1.9_androidx_upgrade
flutter_boost为了实现每个widget页面都有一个native端的activity页面与之对应,那么打开新的flutter页面时,就指定了特殊的打开页面方式:
FlutterBoost.singleton.open();
这个函数的作用就是通知native端,开始创建activity。当native端来到了
setContentView(createFlutterView());
时,就会重新进入到flutter侧的ContainerCoordinator类中的"didInitPageContainer",其实此时并没有实质上的改变,就是创建了一个与ContainerLifeCycle.Init对应的ContainerSettings。当native侧的代码进入到onResume()后,又会发送事件进入到flutter侧的"didShowPageContainer"。此时开始了真正意义上的flutter页面创建。
bool nativeContainerDidShow(String name, Map params, String pageId) {
FlutterBoost.containerManager
?.showContainer(_createContainerSettings(name, params, pageId));
performContainerLifeCycle(_createContainerSettings(name, params, pageId),
ContainerLifeCycle.Appear);
return true;
}
因此需要重点关注ContainerManager中的showContainer()。在这个方法中会先判断_onStage是不是就是要显示的页面,如果不是就从_offStage中查找。其中_onStage定义为当前正在显示的页面。_offStage是存放不是正在显示的页面的集合。如果在_offStage中查找不到,就会进入pushContainer()
void pushContainer(BoostContainerSettings settings) {
……
_offstage.add(_onstage);
_onstage = BoostContainer.obtain(widget.initNavigator, settings);
setState(() {});
……
}
这里新创建了一个BoostContainer。并且赋值给了_onStage,然后通过setStage()刷新widgetTree。由于重写了setStage(),因此当调用进入setStage()之后,又进入了_refreshOverlayEntries()。在该函数中
void _refreshOverlayEntries() {
final OverlayState overlayState = _overlayKey.currentState;
if (overlayState == null) {
return;
}
if (_leastEntries != null && _leastEntries.isNotEmpty) {
for (_ContainerOverlayEntry entry in _leastEntries) {
entry.remove();
}
}
final List<BoostContainer> containers = <BoostContainer>[];
containers.addAll(_offstage);
assert(_onstage != null, 'Should have a least one BoostContainer');
containers.add(_onstage);
_leastEntries = containers
.map<_ContainerOverlayEntry>(
(BoostContainer container) => _ContainerOverlayEntry(container))
.toList(growable: false);
///真正的页面显示是在这里
overlayState.insertAll(_leastEntries);
……
}
最后一行,真正意义上实现了页面显示。
overlayState.insertAll(_leastEntries);
overlayState是系统Navigator管理的overlay的状态。但是我们自始至终都没有使用Navigator啊,这个overlayState是如何生效的呢?根据之前的分析我们了解到ContainerManager作为整个flutterModule的根root,然后提供给了MaterialApp。在ContainerManagerState的build方法中,就是直接生成了一个overlay,返回给了整个flutter使用
@override
Widget build(BuildContext context) {
return Overlay(
key: _overlayKey,
initialEntries: const <OverlayEntry>[],
);
}
此时我们在_refreshOverlayEntries()中获取的overlayState正是这个overlay的state。下面是整个流程的伪代码
class MaterialApp{
//在main.dart中初始化FlutterBoost时返回的
builder:BoostContainerManager(initNavigator)
}
class BoostContainerManager{
builder:Overlay()
}
class _ContainerOverlayEntry extends OverlayEntry{
builder:BoostContainer.copyWith(initNavigator)
}
class BoostContainer extends Navigator{
BoostContainerSettings settings;
}
class BoostContainerSettings{
final WidgetBuilder builder;
//也就是我们在main.dart中注册路由时使用的。
builder:FlutterBoost.singleton.registerPageBuilders();
}