美文网首页
flutter_boost如何接管Navigator

flutter_boost如何接管Navigator

作者: 夏广成 | 来源:发表于2019-11-12 18:22 被阅读0次

    以下分析基于 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();
    }
    
    

    相关文章

      网友评论

          本文标题:flutter_boost如何接管Navigator

          本文链接:https://www.haomeiwen.com/subject/zliqictx.html