前言
在上篇中,我和咱们共享了我对于Android
原生与Flutter
模块混合构建的一些经历,在本篇中,我将和咱们共享Android
原生和Flutter
模块通讯方面的经历。
所谓通讯
事先声明,我这儿所说的通讯,指的便是Android
原生和Flutter
模块之间的办法互调,数据传递。
Flutter
官方供给了Channel
也即渠道通道
协助开发者完成:
-
Flutter
向原生
渠道发送音讯。 -
原生
渠道监听通道并接收音讯。然后,处理逻辑并将数据整合好之后作为响应发送回Flutter
。
Flutter
官方供给了三种Channel
用于跨渠道通讯
Channel | 功能 |
---|---|
MethodChannel | 跨渠道办法互调 |
EventChannel | 跨渠道音讯传递 |
BasicMessageChannel | 跨渠道元数据传递 |
你以为我要开始 1-2-3 开始给你介绍这三种Channel
了吗?不!
官方文档在编写自定义的特定渠道代码一节中,以获取原生渠道电池电量为例演示了怎么运用MethodChannel
进行跨渠道的办法调用,不难发现在MethodChannel
的运用中,有两处(每个渠道)运用了硬编码字符串用于各渠道间的标识、匹配。这还只是调用了一个原生渠道的办法,实际生产中十个,百个办法都是有或许的!
鄙人非常讨厌这种涣散的无法管理的用于标识、匹配的硬编码字符串,由于团队中英文水平参差不齐,即便都很好,谁能确保自己不会手抖拼错呢,这就增加了一个或许的犯错点。因而,官网也在后半篇介绍了一种更安全的跨渠道通讯的办法。
Pigeon
Pigeon
是一个用于Flutter
和原生
渠道之间建立类型安全的通讯的代码生成东西,更快更易用。
Pigeon
免去了在Flutter
和原生
之间用硬编码字符串的办法匹配通道、音讯的名称和数据类型,并要求Flutter
和原生
声明相同的参数和数据类型,生成以结构化类型安全办法发送音讯的代码。
其实,观察Pigeon
生成的代码可以发现,Pigeon
其实也是凭借BasicMessageChannel
完成通讯的,只不过它以脚本的办法生成了模板代码,正是在这个过程中避免了手写硬编码或许出现的问题。
Pigeon
的运用
增加Pigeon
依赖
dart pub add pigeon
然后
dart pub get
创立pigeon
文件夹并新建一个platformApi.dart
文件用于声明对应的办法
这儿
platformApi.dart
的文件命名可自定义
pigeon/platformApi.dart
import 'package:pigeon/pigeon.dart';
// 这是声明 Flutter 调用原生办法
// 如果是原生调用 Flutter 办法,请运用 @FlutterApi() 注解
@HostApi()
abstract class AndroidBatteryApi {
int getAndroidBattery();
}
新建Pigeon
脚本用于生成对应的通讯代码
复制下方代码创立一个run_pigeon.sh
文件,将下方代码复制,针对你的项目修改成对应的文件名,文件路径
$ flutter pub run pigeon \
--input pigeon/platformApi.dart \
--dart_out lib/api_generated.dart \
--experimental_kotlin_out android/app/src/main/kotlin/com/randalldev/native_provider/Pigeon.kt \
--experimental_kotlin_package "com.randalldev.native_provider"
我这儿只生成了Android
渠道的模板代码
pigeon
东西还有其他指令选项,比方iOS
渠道
--objc_header_out ios/Runner/pigeon.h \
--objc_source_out ios/Runner/pigeon.m \
--experimental_swift_out ios/Runner/Pigeon.swift \
执行脚本,会生成各端需求的原生代码
Windows
编译环境,AS
的Terminal
东西内直接输入下方指令
run_pigeon.sh
MacOS
或Liunx
编译环境,AS
的Terminal
东西内需求输入下方指令
./run_pigeon.sh
完成原生办法的逻辑
pigeon
脚本生成代码是接口类,咱们需求完成接口,并完成其内部的办法
翻开android/app/src/main/kotlin/com/randalldev/native_provider/MainActivity.kt
运用延迟加载的办法新建一个实例,这是一种更安全更方便的写法,根据需求的参数挑选内部类的办法有时也可以,关注内部完成即可
private val batteryApi by lazy {
object : AndroidBatteryApi {
override fun getAndroidBatteryApi(): Long {
TODO("Not yet implemented")
}
}
}
TODO部分便是咱们需求完成的Android
渠道的逻辑
针对需求异步操作才能获取回来值的状况
这种状况通常出现在一些网络操作、文件操作的状况。
声明异步的办法
还是之前的platformApi.dart
文件,增加一个异步办法的声明
@async
int getAsyncAndroidBattery();
运转run_pigeon.sh
脚本,生成新声明的办法,并在Android
渠道增加完成
private val batteryApi by lazy {
override fun getAsyncAndroidBattery(callback: (Long) -> Unit) {
TODO("Not yet implemented")
}
}
完成异步逻辑
private val batteryApi by lazy {
override fun getAsyncAndroidBattery(callback: (Long) -> Unit) {
// 演示代码,实际没有这样的 api
system.getBattery(object : BatteryResultListener {
override fun onSucceed(battery: Integer) {
callback.invoke(battery)
}
override fun onFailed(msg: String?) {
callback.invoke(-1)
}
})
}
}
总结
Flutter
供给了Channel
用于完成与原生渠道的通讯,可是基于我个人的技术挑选,我挑选了运用官方供给的代码生成东西Pigeon
去生成Channel
Api 的代码。
运用Pigeon
主要是以下这几个步骤
- 增加依赖
- 创立
pigeon
相关dart
文件并声明需求的办法 - 编写并运转
pigeon
脚本 - 在
原生
渠道完成Pigeon
生成的抽象办法,并回来对应的数据
参阅文章
Writing custom platform-specific code
[Flutter] 运用 Pigeon 完成跨渠道办法调用
Pigeon