文章目录
- 前言
- 集成 flutter 混合开发
- android 与 flutter 之间的通信
- 总结
一、前言
因为flutter 具有跨平台的属性,既可以在android上跑,也能在ios 上跑,所以为了节约开发的成本,减少人力,势必就会用到它。然而已有的项目部不太可能重新写,所以就需要进行混合开发。也就是在原生中集成flutter,进行混合开发。混合开发就会遇到原生和flutter的通信问题,今个就讲讲原生和flutter的通信。
二、首先创建个flutter module,然后集成到app中
1、在原生项目的父目录下,使用命令,创建flutter项目:
flutter create -t module --org com.example flutter_demo
创建完毕,然后我们用as打开这个父目录,可以看到我们的flutter_demo 已经创建好了,如图:
2、在原生app里面的settings.gradle,include ‘:app’ 下面添加:
setBinding(new Binding([gradle: this]))
evaluate(new File(settingsDir.parentFile,'flutter_demo/.android/include_flutter.groovy'
))
include ':flutter_demo'
3、在原生app下的build.gradle中添加依赖:
dependencies {//...implementation project(':flutter')
}
添加完毕,我们切回 app的项目,运行会发现报错了。
报错是说flutterPlugin 没法用,这里在settings.gradle 将repositoriesMode改为:RepositoriesMode.PREFER_PROJECT。重新运行。
如果还遇到第三方解析失败,添加maven:
dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)repositories {maven { url 'https://jitpack.io' }maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }maven { url 'https://maven.aliyun.com/repository/central' }maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }google()mavenCentral()}
}
另外在项目的build.gradel 添加:
allprojects {repositories {maven { url 'https://jitpack.io' }maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }maven { url 'https://maven.aliyun.com/repository/central' }maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }google()mavenCentral()}
}
然后运行app,就可以了。如果你还有其他报错,切换到根目录,去检查下flutter_demo里头的这两个文件。打开main.dart,提示你Enable Dart support,点击它就可以。然后再打开 pubspec.yaml ,点击pub get 获取相应的依赖。确保flutter项目的环境和依赖库没问题。
到这里,我们的flutter_demo 就集成到我们的app中了。接下来就是看android和flutter的通信
三、android和flutter的通信
上面的项目,每次要看flutter代码是不是每次都要切过来切过去的,所以呢,我们可以在setting.gradle 加上这么一行代码:
project(‘:flutter_demo’).projectDir = new File(‘…/flutter_demo’)
这样,我们在app的项目中就能查看flutter的代码了。好了,我们最想知道的就是android 怎么打开 flutter页面。接这往下看。
1、android 跳转 flutter:
在清单AndroidManifest里面添加 FlutterActivity
<activity android:name="io.flutter.embedding.android.FlutterActivity"android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"android:hardwareAccelerated="true"android:windowSoftInputMode="adjustResize"></activity>
点击跳转:
binding.fab.setOnClickListener { view ->//跳转flutterstartActivity(FlutterActivity.createDefaultIntent(this))}
你会发现跳转很慢,所以,我们用带有缓存引擎的初始路由来启动FlutterActivity
创建一个MyApplication 然后 在onCreate 中进行缓存引擎的初始化。
// 创建一个Flutter引擎flutterEngine = new FlutterEngine(this);// 开始执行 Dart 代码来预热flutter引擎flutterEngine.getDartExecutor().executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault());//缓存Flutter引擎用来开启FlutterActivityFlutterEngineCache.getInstance().put("my_engine_id", flutterEngine);}
这个我们就能使用缓存引擎跳转Flutter。
binding.fab.setOnClickListener { view ->//跳转flutterstartActivity(FlutterActivity.withCachedEngine("my_engine_id").build(this));}
很明显立马就跳转过去了。
2、如何跳转不同的flutter页面?
在applation 的onCreate 初始化需要跳转的页面, 到我们的Application 中的onCreate添加:
flutterEngine.getNavigationChannel().setInitialRoute("/test2");
然后修改main.dart 的代码:
void main() => runApp(_widgetForRoute(window.defaultRouteName));Widget _widgetForRoute(String route) {
switch (route) {case '/test1':return const Test1();case '/test2':return const Test2();case '/test3':return const Test3();default:return const Test1();
}
}
Test1是Test1.dart,代表不同的页面。当我们要跳转不同的页面,只要修改
flutterEngine.getNavigationChannel().setInitialRoute(“/test2”);就可以了,比如我们要跳转到Test3页面改成 flutterEngine.getNavigationChannel().setInitialRoute(“/test3”);
这个很简单,根据不同的标识,跳转对应的页面就行了。
四、接下来,就是文章的主题,讲通信方式都有哪些?
BasicMsgChannel
EventChannel
MethodChannel
1、BasicMsgChannel 方式
双向的,原生可以给flutter发送,然后flutter同时也可以返回信息给原生
发送:
val flutterEngine = MyApplication.flutterEngineval basicMessageChannel = BasicMessageChannel(flutterEngine.dartExecutor.binaryMessenger,"basicMessageChannel",StringCodec.INSTANCE)basicMessageChannel.send("通过basicMessageChannel发送消息"){message: String?->Log.d("ssz", "接收:$message") //message 是flutter发回给原生的消息}
flutter 接收:
_basicMessageChannel = const BasicMessageChannel('basicMessageChannel', StringCodec());_basicMessageChannel.setMessageHandler((String? message) => Future<String>((){setState(() {//刷新控件_basicMessage = "flutter接收了消息:${message!}";});return "flutter 收到了";//这里是返回信息给原生}));
我们也可以反过来,原生接收,flutter发送,如下:
原生接收:
basicMessageChannel.setMessageHandler { message, reply ->Log.d("ssz", "接收:$message")}
flutter 发送:
_basicMessageChannel.send("我是flutter的消息");
2、MethodChannel 方法
主要是flutter 调用原生
原生接收:
val methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "test2")binding.btnTest2.setOnClickListener {toFlutter()methodChannel.setMethodCallHandler { call, result ->if (call.method.equals("open")){Log.d("ssz", "接收flutter调用")}}}
flutter 发送
const _methodChannel = MethodChannel('test2');_methodChannel.invokeListMethod("open");
3、EventChannel方法
主要是原生发送给flutter,这个方法使用不当就会接受不到,谨慎使用。
原生发送:
val eventChannel = EventChannel(MyApplication.flutterEngine.dartExecutor.binaryMessenger, "test3")binding.btnTest3.setOnClickListener {toFlutter()eventChannel.setStreamHandler(object : StreamHandler{override fun onListen(arguments: Any?, events: EventSink?) {Log.d("ssz","执行了 onListen");events?.success("原生发送")}override fun onCancel(arguments: Any?) {}})}}
flutter 接收
void initState() {super.initState();Future.delayed(const Duration(milliseconds: 6000), () {//需要做个延迟,不然原生onListen会不执行,导致不能发送消息var eventChannel = const EventChannel("test3");eventChannel.receiveBroadcastStream().listen((dynamic event) {setState(() {_EventMessage = "flutter接收$event";});}, onError: (dynamic error){setState(() {_EventMessage = "flutter接收$error";});},cancelOnError: true);});}
最后呢,关于路由方面,有的业务可能需要跳转很多不同的页面,原生的方式不太友好,可以选择闲鱼开源的库 https://github.com/alibaba/flutter_boost ,提高开发的效率。
以上代码地址:https://github.com/shenshizhong/HybridFlutter
总结
总的来讲:
1、android集成flutter,进行混合开发
2、android 与 flutter 的通信
3、使用第三方提高开发效率
如果对你有一点点帮助,那是值得高兴的事情。:)
我的csdn:http://blog.csdn.net/shenshizhong
我的简书:http://www.jianshu.com/u/345daf0211ad