Flutter 如何接入 已有Android项目?

背景

flutter目前一片火热,相信很多小伙伴都跃跃欲试。但现状是很多公司都有稳定的Android/ios项目,想完全用flutter重写,完全不现实,毕竟,世上没那么多"闲鱼"。

所以我们要思考的是,如何把flutter接入到原生项目当中。
这里主要参考的还是官方文档传送门

主要的执行步骤如下:

1. 在你的Android工程目录同级目录下执行命令

假设你的项目的根目录为/xxx/pro,则需要在/xxx下(主目录的下一级也可以,后续会讲到)执行以下命令

flutter create -t module flutter_module

2. 打开你的Android工程的setting.gradle文件

从setBinding处添加,这里有一点要注意一下,

  • 假设第一步你创建的flutter_module在你的项目之下,则配置路径时候需要加上你的项目名
    FlutterHybrid/flutter_module/.android/include_flutter.groovy
  • 假设第一步你创建的flutter_module跟你的项目是平级,则配置路径时候不需要加上你的项目名
    flutter_module/.android/include_flutter.groovy
include ':app'

setBinding(new Binding([gradle: this]))
println("settingsDir.parentFile=" + settingsDir.parentFile)
evaluate(new File(settingsDir.parentFile, 'FlutterHybrid/flutter_module/.android/include_flutter.groovy'))

3. 最后打开你的app目录下的build.gradle

implementation project(':flutter')

使用姿势

准备工作已经完毕,接下来就是拉起一个flutter的页面。
官方提供了两种 原生模块拉起flutter模块的方式:

  1. 直接createView创造一个flutterView,把他添加到你的布局中
    730571-3a56aa7d83367eac.png
    createView方式

    最后一项"/setting" 是对应flutter的路由指向的页面,关于路由这里就暂时放一下,后续会提到。
  2. 使用fragment的方式
    730571-8f3fcff848c65a26.png
    fragment方式

    以上就是两种元素模块应用flutter模块的方式,实际上看过FlutterFragment的源码你就会发现,他也是调用了Flutter.createView返回一个FlutterView,最终都是添加了一个flutterView到原生中而已.

flutter调用原生能力

主要参考文档 传送门

730571-997ffddd26a2fb36.png
MethodChannel

MethodChannel(flutterView, FLUTTER_CHANNEL_NAME).setMethodCallHandler { call, result ->
            if (call.method == "add") {
                Log.d("111", "enter test")
                try {
                    val a = call.argument<Int>("a")
                    val b = call.argument<Int>("b")
                    Log.d("111", "a=$a , b=$b")

                    val res = doRealAdd(a, b)
                    result.success(res)
                } catch (e: ClassCastException) {
                    e.printStackTrace()
                }
            } else {
                result.notImplemented()
            }
        }

以上就是原生的实现部分,然后,flutter那边如何调用呢?

Future<void> requestAdd() async {
        try {
            final int result = await platform.invokeMethod(MNAME_TEST,
                <String, dynamic>{
                     'a': 20,
                     'b': 30,
                   });
            debugPrint('result add = $result .');
        } on PlatformException catch (e) {
            debugPrint("Failed to get battery level: '${e.message}'.");
        }

    }

以上的样例代码涉及了 flutter如何调用native的哪个函数,传递什么参数,可以拿到什么返回值。当然,支持的数据类型也是有限制的。

730571-0665fe7efd262884.png
支持的数据格式

我们要发送自定义类型数据过去如何办?
显然,我们需要转换为dart支持的类型,也许,你可能想到了Object->Json,然后,到了flutter那边,在变为Json对象即可。
不过也有其他的方式,比如,你们恰好使用的是protobuf的话,那么直接传byte[]肯定很不错啦,再者,你还可以实现自定义协议,如果有足够的时间的话。总之传递的数据需要是平台之间都能识别的类型。

原生向flutter发送数据

参考资料 EventChannel
native端代码如下:

730571-914df28bf0749a9b.png
native端代码

flutter端代码如下:


730571-9deac7a484a80840.png
flutter端代码

总结

原生拉起flutter做的页面以及flutter调用原生模块以及原生模块推送数据到flutter经过验证都是ok的,因此flutter接入现有的app这条路是可行的。
以上样例代码均已上传到github戳我戳我
如果这篇文章对你有收获,请帮忙点赞和分享,多谢。

猜你喜欢

转载自blog.csdn.net/weixin_34054931/article/details/90957870