在实际开发过程中,往往我们会是基于原有项目结合flutter开发的混合开发模式。因此,我们有必要来看看闲鱼开发一个混合通信方案-flutterboost。就目前使用的情况来看,这套方案对开发者比较友好,闲鱼官方一直在维护,值得推荐。来一波地址:Flutterboost

集成步骤其实官网都有,我这里就简单列一下,方便大家参考,具体可以参照官方文档。

一、首先你得有一个flutter的module项目,记住是module模式的项目,下面是 mac 电脑Android Studio Arctic Fox | 2020.3.1 Patch 4 版本的新建flutter module过程。

1.file--new flutter project

android原生和flutter混合 flutter原生混合开发_android studio

2. 选择flutter的sdk目录,这个提前下好,不明白的,百度一下flutter安装教程哈。

android原生和flutter混合 flutter原生混合开发_Android_02

3.这里主要记得填项目名和选择project type为module,其他自己看着选就行了 。继续点finish,就完成了。

android原生和flutter混合 flutter原生混合开发_android studio_03

二、有了flutter_module项目,既然是混合开发,原生Android项目和原生ios项目是少不了,按正常方式新建就好了。这里注意下,不是说一定要flutter,ios,android三个项目齐全才能开发运行的意思哈,不需要ios平台的包自然就不需要新建ios项目了。最终的目录结构参考如下,当然,也可以原生项目文件里嵌套flutter_module项目,只是后面配置引用关联的时候,要调整一下配置,但是嵌套没必要,不建议。

android原生和flutter混合 flutter原生混合开发_flutter_04

 好了,至此,三个项目都有了,下面看下,Android项目是如何关联flutter module的,原理其实很简单,就是把flutter项目当成安卓的一个module关联起来而已,这种方式Android里面经常用到, ios应该也差不多,ios的同学可以参考官网配置。

1.用Android studio打开flutter_module项目,找到pubspec.yaml文件,在dependencies:下添加flutterboost的依赖。然后点击右上角的pub get加载依赖。

flutter_boost: git: url: 'https://github.com/alibaba/flutter_boost.git' ref: 'v3.0-null-safety-preview.18'

2.运行flutter_module项目,正常情况是可以运行起来,并且显示默认的flutter界面效果。检查项目中是否存在.android和.ios目录。

android原生和flutter混合 flutter原生混合开发_android studio_05

3.没问题后,打开Android项目,找到settings.gradle文件,新增下面代码。主要根据自己的实际情况修改路径。

/**
 * 这里注意evaluate 里面file路径参数的第二个参数,是flutter项目里.android目录的groovy的具体路径,
 * 其中flutter_module 是flutter的项目名,不是固定的,根据自己实际的flutter项目名修改。
 *
 */
setBinding(new Binding([gradle: this]))
evaluate(new File(
        settingsDir.parentFile,
        '/flutter_module/.android/include_flutter.groovy'
))
include ':flutter_module'
project(':flutter_module').projectDir = new File('/flutter_module')

 4.找到app的gradle文件,新增依赖

implementation project(':flutter')
    implementation project(':flutter_boost')

5.在清单文件添加注册信息。

<activity
        android:name="com.idlefish.flutterboost.containers.FlutterBoostActivity"
        android:theme="@style/Theme.AppCompat"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize" >

</activity>
<meta-data android:name="flutterEmbedding"
           android:value="2">
</meta-data>

6.同步sync Android 项目,并运行,正常情况这个时候能正常运行起来项目。如有报错,可以留言或者查看flutterboost官网集成文档。

集成完毕后,接下来看看如何实现初始化和基本使用。

7.在Android 项目的application里面初始化。

private fun initFlutter(context: Application ){
            val delegate=  MyFlutterBoostDelegate()
            FlutterBoost.instance().setup(context, delegate,
                    FlutterBoost.Callback { engine: FlutterEngine -> engine.plugins
                    }
            )
        }

MyFlutterBoostDelegate 类很简单 ,class MyFlutterBoostDelegate:FlutterBoostDelegate {

},重写下面2个方法就ok了。这2个方法多提一嘴,当你使用flutterboost的跳转api在原生和flutter直接跳转的时候,这2个方法才会回调。

FlutterBoost.instance().setup(this, new FlutterBoostDelegate() {
            @Override
            public void pushNativeRoute(FlutterBoostRouteOptions options) {
                //这里看方法名,很明显是打开原生页面的回调,
                //根据options.pageName来判断 跳转哪个页面.跳转逻辑和原生跳转代码一样。
                /**
                 *FlutterBoost.instance().currentActivity()
                 *.startActivityForResult(intent, options.requestCode())
                **/
                 
            }

            @Override
            public void pushFlutterRoute(FlutterBoostRouteOptions options) {
                Intent intent = new FlutterBoostActivity.CachedEngineIntentBuilder(FlutterBoostActivity.class)
                        .backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)
                        .destroyEngineWithActivity(false)
                        .uniqueId(options.uniqueId())
                        .url(options.pageName())
                        .urlParams(options.arguments())
                        .build(FlutterBoost.instance().currentActivity());
                FlutterBoost.instance().currentActivity().startActivity(intent);
            }
        }, engine -> {
        });

8. 打开flutter_module项目找到main.dart文件, 修改内容如

这个是flutterboost官网代码可自行参考。);

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';

void main() {
  ///这里的CustomFlutterBinding调用务必不可缺少,用于控制Boost状态的resume和pause
  CustomFlutterBinding();
  runApp(MyApp());
}


///创建一个自定义的Binding,继承和with的关系如下,里面什么都不用写
class CustomFlutterBinding extends WidgetsFlutterBinding with BoostFlutterBinding {}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  /// 由于很多同学说没有跳转动画,这里是因为之前exmaple里面用的是 [PageRouteBuilder],
  /// 其实这里是可以自定义的,和Boost没太多关系,比如我想用类似iOS平台的动画,
  /// 那么只需要像下面这样写成 [CupertinoPageRoute] 即可
  /// (这里全写成[MaterialPageRoute]也行,这里只不过用[CupertinoPageRoute]举例子)
  ///
  /// 注意,如果需要push的时候,两个页面都需要动的话,
  /// (就是像iOS native那样,在push的时候,前面一个页面也会向左推一段距离)
  /// 那么前后两个页面都必须是遵循CupertinoRouteTransitionMixin的路由
  /// 简单来说,就两个页面都是CupertinoPageRoute就好
  /// 如果用MaterialPageRoute的话同理

  Map<String, FlutterBoostRouteFactory> routerMap = {
    'mainPage': (RouteSettings settings, String uniqueId) {
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            Map<String, Object> map = settings.arguments as Map<String, Object> ;
            String data = map['data'] as String;
            return MainPage(
              data: data,
            );
          });
    },
    'simplePage': (settings, uniqueId) {
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            Map<String, Object> map = settings.arguments as Map<String, Object>;
            String data = map['data'] as String;
            return SimplePage(
              data: data,
            );
          });
    },
  };

  Route<dynamic> routeFactory(RouteSettings settings, String uniqueId) {
    FlutterBoostRouteFactory func = routerMap[settings.name] as FlutterBoostRouteFactory;
    return func(settings, uniqueId);
  }

  Widget appBuilder(Widget home) {
    return MaterialApp(
      home: home,
      debugShowCheckedModeBanner: true,

      ///必须加上builder参数,否则showDialog等会出问题
      builder: (_, __) {
        return home;
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return FlutterBoostApp(
      routeFactory,
      appBuilder: appBuilder,
    );
  }
}

class MainPage extends StatelessWidget {
  const MainPage({Object data});
  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(child: Text('Main Page')),
    );
  }
}

class SimplePage extends StatelessWidget {
  const SimplePage({Object data});
  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body:  Center(child: Text('SimplePage')),
    );
  }
}

9.跳转方法,可以单独写个类,

class FBRouteManager {
  ///跳转
  static Future push(String routeName, [Map<String, dynamic>? parameter]) {
    return BoostNavigator.instance
        .push(routeName, withContainer: false, arguments: parameter);
  }
}

到这里基本已经集成完毕了。由于版幅有限,如有问题,欢迎留言。