Skip to content
flutter_boost_demo,目前基于flutter:v1.5.4-hotfix.2,flutter_boost:0.5.2
Dart Java
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
app
flutter_module
.gitignore
build.gradle
gradle.properties
readme.md
settings.gradle

readme.md

集成Flutter_boost

flutter_boost 地址:https://github.com/alibaba/flutter_boost 集成之后的项目地址:https://github.com/huangyuanlove/flutter_boost_demo flutter版本: v1.5.4-hotfix.2 flutter_boost版本:0.1.52

集成过程

前提:项目已经集成flutter,并且可以运行

添加依赖

根据官方说法: 打开pubspec.yaml并将以下行添加到依赖项:

flutter_boost: ^0.1.52

或者可以直接依赖github的项目的版本,Tag,pub发布会有延迟,推荐直接依赖Github项目

flutter_boost:
        git:
            url: 'https://github.com/alibaba/flutter_boost.git'
            ref: '0.1.52'
            

然后 flutter packages get一下

在主工程的build.gradle中依赖一下 implementation project(path: ':flutter_boost'),官方没有提这个,但是我在项目中不添加这个依赖,找不到对应的类

在flutter_nodule侧

main.dart中注册一下路由,过程和使用命名路由相似

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();

    FlutterBoost.singleton.registerPageBuilders({
      'first': (pageName, params, _) => FirstRouteWidget(),
      'second': (pageName, params, _) => SecondRouteWidget(params),
      'tab': (pageName, params, _) => TabRouteWidget(),
      'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params),

      ///可以在native层通过 getContainerParams 来传递参数
      'flutterPage': (pageName, params, _) {
        print("flutterPage params:$params");

        return FlutterRouteWidget();
      },
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Boost example',
        builder: FlutterBoost.init(postPush: _onRoutePushed),
        home: Container());
  }

  void _onRoutePushed(
      String pageName, String uniqueId, Map params, Route route, Future _) {
  }
  

其中 FirstRouteWidgetSecondRouteWidgetTabRouteWidgetFragmentRouteWidgetFlutterRouteWidget代码可以在simple_page_widgets.dart中找到

在原生Android侧

修改Application继承FlutterApplication,并且在onCreate初始化FlutterBoost

        FlutterBoost.init(new Platform() {

            @Override
            public Application getApplication() {
                return MyApplication.this;
            }

            @Override
            public boolean isDebug() {
                return true;
            }

            @Override
            public void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode, Map<String, Object> exts) {
                //在flutter中调用FlutterBoost.singleton.open()方法,最终会走到这里进行处理
                PageRouter.openPageByUrl(context,url,urlParams,requestCode);
            }

            @Override
            public IFlutterEngineProvider engineProvider() {
                return new BoostEngineProvider(){
                    @Override
                    public BoostFlutterEngine createEngine(Context context) {
                        return new BoostFlutterEngine(context, new DartExecutor.DartEntrypoint(
                                context.getResources().getAssets(),
                                FlutterMain.findAppBundlePath(context),
                                "main"),"/");
                    }
                };
            }

            @Override
            public int whenEngineStart() {
                return ANY_ACTIVITY_CREATED;
            }

            @Override
            public void registerPlugins(PluginRegistry registry) {
                super.registerPlugins(registry);
            }
        });

Android侧包含flutter_view的容器,比如Activity需要继承BoostFlutterActivity,并实现getContainerUrl()getContainerUrlParams()方法 其中getContainerUrl方法返回的值就是在main.dart中注册的路由,getContainerUrlParams方法返回值则是对应的params

尝试

目前的做法是在Android这边配置打开的协议,和iOS统一,打开页面之后传递的参数全部附加在Uri上, 比如在flutter中的调用打开另外一个flutter界面,第一个参数uri就是sample://flutter/launch,如果是打开native页面,则是sample://native/launch 这样两端各自处理各自的逻辑就好了。 在Android端, PageRouter类用来处理native和flutter页面互相打开的逻辑,将传递进来的参数拼接成Uri的形式,通过Intent.setData()方式传递到下一个页面,而不用关系是打开native还是flutter, 在FlutterView的容器FlutterPageActivity中,我们通过解析Uri,还原一下要打开的flutter页面的router以及需要的参数,通过上面说的两个方法传递给flutter。

flutter_boost流程

在flutter中打开flutter或者原生
FlutterBoost.singleton.open("sample://nativePage", urlParams:{
  "query": {"aaa": "bbb"}
})
  Future<Map<String,dynamic>> open(String url,{Map<String,dynamic> urlParams,Map<String,dynamic> exts}){

    Map<String, dynamic> properties = new Map<String, dynamic>();
    properties["url"] = url;
    properties["urlParams"] = urlParams;
    properties["exts"] = exts;
    return channel.invokeMethod<Map<String,dynamic>>(
        'openPage', properties);
  }

这里也是通过channel调用原生的方法,方法名字是openPage

在FlutterBoost.BoostMethodHandler中

case "openPage":
                {
                    try {
                        Map<String,Object> params = methodCall.argument("urlParams");
                        Map<String,Object> exts = methodCall.argument("exts");
                        String url = methodCall.argument("url");

                        mManager.openContainer(url, params, exts, new FlutterViewContainerManager.OnResult() {
                            @Override
                            public void onResult(Map<String, Object> rlt) {
                                if (result != null) {
                                    result.success(rlt);
                                }
                            }
                        });
                    }catch (Throwable t){
                        result.error("open page error",t.getMessage(),t);
                    }
                }
                break;

这里的mManager是FlutterViewContainerManager一个实例,openContainer方法的实现是这样的

    void openContainer(String url, Map<String, Object> urlParams, Map<String, Object> exts,OnResult onResult) {
        。。。
        FlutterBoost.singleton().platform().openContainer(context,url,urlParams,requestCode,exts);
    }

注意最后一句FlutterBoost.singleton().platform()这里的platform返回的是 IPlatform类型,也就是我们在Application中初始化FlutterBoost时传入的对象

FlutterBoost.init(new Platform(){...})

最终调用了这里面的openContainer方法,将路由处理交给了原生。

在flutter中关闭页面

调用

BoostContainerSettings settings = BoostContainer.of(context).settings;
FlutterBoost.singleton.close(settings.uniqueId,result: {"result":"data from second"});

在上面的flutter打开原生或者flutter页面时传的map参数,打下断点或者输出一下,可以看到里面会有一个__container_uniqueid_key__, 这个key是flutter_boost用来标示flutterview的容器,当我们需要在flutter中关闭页面的时候,需要传入这个key。 而关闭页面的时候

case "closePage":
            {
                try {
                    String uniqueId = methodCall.argument("uniqueId");
                    Map<String,Object> resultData = methodCall.argument("result");
                    Map<String,Object> exts = methodCall.argument("exts");

                    mManager.closeContainer(uniqueId, resultData,exts);
                    result.success(true);
                }catch (Throwable t){
                    result.error("close page error",t.getMessage(),t);
                }
            }

也是通过FlutterViewContainerManager的实例进行关闭

IContainerRecord closeContainer(String uniqueId, Map<String, Object> result,Map<String,Object> exts) {
    IContainerRecord targetRecord = null;
    for (Map.Entry<IFlutterViewContainer, IContainerRecord> entry : mRecordMap.entrySet()) {
        if (TextUtils.equals(uniqueId, entry.getValue().uniqueId())) {
            targetRecord = entry.getValue();
            break;
        }
    }

    if(targetRecord == null) {
        Debuger.exception("closeContainer can not find uniqueId:" + uniqueId);
    }

    FlutterBoost.singleton().platform().closeContainer(targetRecord,result,exts);
    return targetRecord;
}

调用FlutterBoost.singleton().platform()的关闭容器方法

@Override
public void closeContainer(IContainerRecord record, Map<String, Object> result, Map<String, Object> exts) {
    if(record == null) return;

    record.getContainer().finishContainer(result);
}

最终还是调用的record中container的finish方法。 而在ContainerRecord类(IContainerRecord的实现类)的onAppear方法中,会将当前页面放入自己维护的栈中。 具体执行顺序: 当打开FlutterView的容器(这里是我们自己继承自BoostFlutterActivity的类,实现了finishContainer()方法),在BoostFlutterActivity.onCreate()中,调用 FlutterBoost.singleton().containerManager().generateSyncer(this);,将当前的容器放在FlutterViewContainerManager中,并且记录上面讲到唯一标示 当关闭容器的时候,则从里面查找到对应的容器,执行finishContainer()。


graph LR
	a --- b
You can’t perform that action at this time.