背景
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模块的方式:
- 直接createView创造一个flutterView,把他添加到你的布局中
最后一项"/setting" 是对应flutter的路由指向的页面,关于路由这里就暂时放一下,后续会提到。 - 使用fragment的方式
以上就是两种元素模块应用flutter模块的方式,实际上看过FlutterFragment的源码你就会发现,他也是调用了Flutter.createView
返回一个FlutterView,最终都是添加了一个flutterView到原生中而已.
flutter调用原生能力
主要参考文档 传送门
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的哪个函数,传递什么参数,可以拿到什么返回值。当然,支持的数据类型也是有限制的。
我们要发送自定义类型数据过去如何办?
显然,我们需要转换为dart支持的类型,也许,你可能想到了Object->Json,然后,到了flutter那边,在变为Json对象即可。
不过也有其他的方式,比如,你们恰好使用的是protobuf的话,那么直接传byte[]肯定很不错啦,再者,你还可以实现自定义协议,如果有足够的时间的话。总之传递的数据需要是平台之间都能识别的类型。
原生向flutter发送数据
参考资料 EventChannel
native端代码如下:
flutter端代码如下:
总结
原生拉起flutter做的页面以及flutter调用原生模块以及原生模块推送数据到flutter经过验证都是ok的,因此flutter接入现有的app这条路是可行的。
以上样例代码均已上传到github戳我戳我
如果这篇文章对你有收获,请帮忙点赞和分享,多谢。