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();
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 该文章属于刘小壮原创,转载请注明:刘小壮[https://www.jianshu.com/u/2de707c93d...
    刘小壮阅读 6,867评论 1 30
  • 今天我和哥哥还有妈妈陪爸爸去临沂办事却爸爸看天有点黑,就带着我们去找酒店住下,找了好久,终于找到了,第二天早晨我和...
    直面人生_0165阅读 163评论 0 0
  • 《白说》与《看见》 这是2019年,我的的第一份阳光。 某个也似微阳的日子里 我本着买方格本的心,却走进一家书店 ...
    木易济慈阅读 643评论 3 2
  • webcal://p07-calendars.icloud.com/published/2/TbB4otDpTal...
    玥霖霏霏阅读 155评论 0 0
  • 太容易付出 却不容易相处 难怪我总是被辜负 太多的领悟 却太少的幸福 是天生性格太顽固 我行我素那样又何苦 我又不...
    金音阅读 164评论 0 3