美文网首页Android开发经验谈
Flutter混合项目搭建之Flutter_Boot的使用

Flutter混合项目搭建之Flutter_Boot的使用

作者: zhx喜籽 | 来源:发表于2020-01-02 21:31 被阅读0次

    一、概念

    1、Flutterr_Boot

    这是一个由咸鱼技术出品,帮助你在已有原生应用的情况下,搭建flutter混合开发环境的工具。 它提供了标准的混合工程结构,同时支持混合栈(一套原生和flutter之前页面通信和过渡的方案)的快速接入。

    https://github.com/alibaba-flutter/flutter-boot

    2、Flutter_Boost

    官网介绍:新一代Flutter-Native混合解决方案。 FlutterBoost是一个Flutter插件,它可以轻松地为现有原生应用程序提供Flutter混合集成方案。FlutterBoost的理念是将Flutter像Webview那样来使用。在现有应用程序中同时管理Native页面和Flutter页面并非易事。 FlutterBoost帮你处理页面的映射和跳转,你只需关心页面的名字和参数即可(通常可以是URL)。

    https://github.com/alibaba/flutter_boost

    二、准备工作

    npm安装以及环境配置
    flutter 的v1.9.1-hotfixes分支安装以及环境配置,对应flutter_boost版本是0.1.60---0.1.64
    JDK,Android SDK 等环境配置正确

    三、开始混合项目搭建

    项目地址:https://github.com/jingzhanwu/FlutterHybrid-FlutterBoot
    1、安装flutter_boot,命令行执行:npm install flutter_boot

    npm install flutter_boot
    2、初始化flutter_boot项目,进入要存放工程的目录执行:

    flutter-boot init
    接着会提示你输入工程名称


    image.png

    输完工程名会一次提示你输入flutter 仓库地址、是否有android项目,是否有IOS项目、关联本地项目等,根据自己项目需求选择即可,如果你已经有了android原生项目,则最好在关联android项目哪一步输入本地native项目的路劲进行关联,如果选择不关联也可以,后面后说道如果关联,因为我是第二次创建,所以就默认执行了之前选择的。

    上面都执行完毕后在本地就会生成一个项目,名称就是刚输入的flutter_lib

    3、编译flutter_lib项目,下载配置gradle,如果是android studio 直接打开项目也可以

    依次执行下面命令,第一个命令是进入到项目根目录

    cd flutter_lib

    flutter build apk


    4、如果初始化的时候没有关联native项目,则在原生项目根目录下运行下面命令进行关联、如果初始化时已经关联则跳过此步骤。
    进入native项目根目录执行:flutter-boot link "flutter项目的本地目录",link后面为flutter项目本地目录


    重新关联:flutter-boot link -f "flutter项目的本地目录"

    这一步是将原生项目与flutter项目进行软关联,这一步执行完毕已经就可以进行正常的混合开发了

    5、使用flutter_boost,添加混合栈

    执行:flutter-boot use

    flutter-boot use
    这一步执行完毕,会在原生项目的app下build.gradle、settings.gradle和gradle.properties文件中生成一些配置信息,具体如下

    gradle.properties文件


    settings.gradle文件

    app下build.gradle文件


    除了以上增加的内容外,还会多出来两个gradle文件,分别是flutter的build.gradle和flutter-boost的build.gradle文件;他们分别对应flutter_lib(flutter侧)和flutter_boost库的gradle配置,一般情况下不要去修改这两个文件中的内容,否则会引起一些编译错误。

    6、初始化flutter-boost

    执行完flutter-boot use 命令后分别会在native侧和flutter侧的项目根目录下生成一些初始化使用的事例代码,可以参考;native侧的在 fb目录下,flutter的在main.dart和my_flutter_boost_app.dart文件中。

    Native侧我把生成的事例代码进行了整理,首先是Application中的初始化部分:FlutterInitializer.init(this);

    public class App extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            FlutterInitializer.init(this);
        }
    }
    

    FlutterInitializer.java的部分

    public class FlutterInitializer {
        private final static String TAG = FlutterInitializer.class.getSimpleName();
     
     
        public static void init(Application app) {
            if (!(app instanceof FlutterApplication)) {
                FlutterMain.startInitialization(app);
            }
     
            //路由,Flutter 启动Native页面的时候回调这里
            INativeRouter router = (context, url, urlParams, requestCode, exts) -> {
                String assembleUrl = Utils.assembleUrl(url, urlParams);
                PageRouter.openPageByUrl(context, assembleUrl, urlParams);
            };
            //插件注册
            FlutterBoost.BoostPluginsRegister pluginsRegister = mRegistry -> {
                GeneratedPluginRegistrant.registerWith(mRegistry);
                //注册native的TextView插件,插件名称:TextPlatformViewPlugin
                TextPlatformViewPlugin.register(mRegistry.registrarFor("TextPlatformViewPlugin"));
            };
            //配置
            Platform platform = new FlutterBoost.ConfigBuilder(app, router)
                    .isDebug(true)
                    .whenEngineStart(FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)
                    .renderMode(FlutterView.RenderMode.texture)
                    .pluginsRegister(pluginsRegister)
                    .build();
     
            //初始化flutter_boost
            FlutterBoost.instance().init(platform);
        }
    }
    

    PageRouter.java:是一个自定义的路由控制辅助类,方便管理页面跳转

    public class PageRouter {
     
        public final static Map<String, String> pageName = new HashMap<String, String>() {{
     
            put("first", "first");
            put("second", "second");
            put("tab", "tab");
            put("sample://flutterPage", "flutterPage");
            put("sample://demoFlutterPage", "flutterDemoPage");
        }};
     
        public static final String NATIVE_PAGE_URL = "sample://nativePage";
     
        public static final String FLUTTER_DEMO_PAGE_URL = "sample://demoFlutterPage";
        public static final String FLUTTER_PAGE_URL = "sample://flutterPage";
        public static final String FLUTTER_FRAGMENT_PAGE_URL = "sample://flutterFragmentPage";
     
        public static boolean openPageByUrl(Context context, String url, Map params) {
            return openPageByUrl(context, url, params, 0);
        }
     
        public static boolean openPageByUrl(Context context, String url, Map params, int requestCode) {
     
            String path = url.split("\\?")[0];
     
            Log.i("openPageByUrl", path);
     
            try {
                if (pageName.containsKey(path)) {
                    //打开指定url的flutter页面
                    Intent intent = BoostFlutterActivity.withNewEngine().url(pageName.get(path)).params(params)
                            .backgroundMode(BoostFlutterActivity.BackgroundMode.opaque).build(context);
                    if (context instanceof Activity) {
                        Activity activity = (Activity) context;
                        activity.startActivityForResult(intent, requestCode);
                    } else {
                        context.startActivity(intent);
                    }
                    return true;
                } else if (url.startsWith(FLUTTER_FRAGMENT_PAGE_URL)) {
                    //打开flutter创建的fragment
                    context.startActivity(new Intent(context, FlutterFragmentPageActivity.class));
                    return true;
                } else if (url.startsWith(NATIVE_PAGE_URL)) {
                    //打开原生Activity
                    context.startActivity(new Intent(context, NativePageActivity.class));
                    return true;
                }
                return false;
            } catch (Throwable t) {
                return false;
            }
        }
    }
    

    flutter侧的代码我整理到lib下了,具体如下

    main.dart文件,我自己在生成的事例代码上添加了自己的一些逻辑

    void main() => runApp(MyFlutterBoostApp({
          'embeded': (pageName, params, String id) => EmbededFirstRouteWidget(),
          'first': (pageName, params, String id) => FirstRouteWidget(),
          'second': (pageName, params, String id) => SecondRouteWidget(),
          'tab': (pageName, params, String id) => TabRouteWidget(),
          'platformView': (pageName, params, String id) => PlatformRouteWidget(),
          'flutterDemoPage': (String url, Map params, String id) =>
              MyHomePage(title: '$url $id'),
          'flutterPage': (String pageName, Map params, String id) =>
              FlutterRouteWidget(params: params),
          'flutterFragment': (String url, Map params, String id) =>
              FragmentRouteWidget(params),
        }));
    my_flutter_boost_app.dart文件
    
    class MyFlutterBoostApp extends StatefulWidget {
      final Map<String, PageBuilder> builders;
     
      MyFlutterBoostApp(this.builders);
     
      @override
      _MyFlutterBoostAppState createState() => _MyFlutterBoostAppState();
    }
     
    class _MyFlutterBoostAppState extends State<MyFlutterBoostApp> {
      @override
      void initState() {
        super.initState();
        FlutterBoost.singleton.registerPageBuilders(widget.builders);
      }
     
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          builder: FlutterBoost.init(postPush: _onRoutePushed),
          home: Container(),
        );
      }
     
      void _onRoutePushed(
        String pageName,
        String uniqueId,
        Map params,
        Route route,
        Future _,
      ) {
        print("flutter端路由:pageName:$pageName\n params:$params\n route:$route");
      }
    }
    

    核心代码为: FlutterBoost.singleton.registerPageBuilders(widget.builders)这句,flutter-boost注册一个flutter 的widget供native侧通过url来调用。

    7、manifest文件的配置

    必须注册这个activity,否则无法打开flutter页面

     <!--        这个必须注册,不然无法打开flutter的页面-->
            <activity
                android:name="com.idlefish.flutterboost.containers.BoostFlutterActivity"
                android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
                android:hardwareAccelerated="true"
                android:screenOrientation="portrait"
                android:theme="@style/Theme.AppCompat"
                android:windowSoftInputMode="adjustResize">
                <meta-data
                    android:name="io.flutter.embedding.android.SplashScreenDrawable"
                    android:resource="@drawable/page_loading" />
     
            </activity>
    

    在每个需要使用flutter页面的activity中都要加入android:hardwareAccelerated="true"这个属性的配置

    8、如果native项目出现support库重复的情况,可以在项目的build.gradle文件中加入以下代码来排除重复包

    def addRepos(RepositoryHandler handler) {
        handler.google()
        handler.jcenter()
        handler.maven { url "https://jitpack.io" }
    }
     
    allprojects {
        //循环所有依赖,指定support的版本为28.0.0,解决重复包问题
        //此方法在编译的时候会循环依赖,所以会增加编译时间。建议在
        //依赖的时候使用exclude 方法排除可能重复的包
        addRepos(repositories)
        subprojects {
            project.configurations.all {
                resolutionStrategy.eachDependency { details ->
                    if (details.requested.group == 'com.android.support'
                            && !details.requested.name.contains('multidex')) {
                        details.useVersion "28.0.0"
                    }
                }
            }
        }
    }
    

    以上就是flutter-boot混合项目脚手架的使用以及flutter-boost的配置了,每一步都是本人自己通过动手实践验证过的,如过程中有错误,首页确认以下flutter版本和使用的flutter-boost的版本,版本对应关系以flutter-boost官网介绍为准https://github.com/alibaba/flutter_boost

    简易MVP,支持Jetpack:https://blog.csdn.net/qq_19979101/article/details/103691091

    Flutter中Sqlite使用:https://blog.csdn.net/qq_19979101/article/details/93030803

    Flutter的Stomp-websocket插件:https://blog.csdn.net/qq_19979101/article/details/93873731

    原文作者:与猿同行
    原文链接:https://blog.csdn.net/qq_19979101/article/details/103777979

    相关文章

      网友评论

        本文标题:Flutter混合项目搭建之Flutter_Boot的使用

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