前言
pigeon
是谷歌官方的一个为了方便开发者在Flutter与原生通信时需要维护大量的成员变量出的一个基于dart
代码自动生成三端代码的插件,可以极大的提高原生混合开发时通信的开发效率,如果使用MethodChannel
、EventChannel
等,需要维护三端的变量,方法名等,通信数据多的话,会对维护造成很大的压力,但是用了pigeon
这个插件,就不需要维护这些变量了,全部自动生成,并且所有的数据都是以对象的形式传递,非常的面向对象。接下来就让我看下如何使用这个插件。
当然如果你想开发一个packages
插件,用这个也是非常方便的。
引入插件:
在dev_dependencies
:下引入 pigeon: ^3.0.3
。目前最新版本。
这里以最新版本为例:
dev_dependencies:
flutter_test:
sdk: flutter
pigeon: ^3.0.3 #生成跨端协议文件用于跨端通信
创建传输数据实体类
需要实现的功能:
1、原生(Android和iOS)调用Flutter
2、Flutter调用原生(Android和iOS)
3、可携带自定义参数、可返回自定义结果、可异步返回。
Android实现步骤:
1、新建一个pigeons文件夹与lib同级目录存储生成的类
我这里分别创建input和output两个文件夹,input是我们编写的目录,output是自动生成的目录。
2、创建.sh脚本用来执行插件
flutter pub run pigeon \
--input pigeons/input/pigeon_input.dart \
--dart_out pigeons/output/pigeon_out.dart \
--objc_header_out pigeons/output/iOSPigeon.h \
--objc_source_out pigeons/output/iOSPigeon.m \
--java_out pigeons/output/AndroidPigeon.java \
--objc_prefix FLT \
--java_package "com.instrument.plugins"
上面脚本内容分别代表执行的dart
文件和分别输出的4个文件的目录地址和Android的包名。
生成之后将这四个文件分别粘贴到我们对应的项目中即可。
注:这里的文件名只是说明,在粘贴的时候我们需要进行重新命名,增强代码的可读性。
3、创建pigeon
需要的基于dart
的实现类pigeon_input
:
import 'package:pigeon/pigeon.dart';
/// 原生数据
class NativeBean {
final int id;
final String name;
NativeBean(this.id, this.name);
}
/// Flutter数据
class FlutterBean {
final int fId;
final String fName;
FlutterBean(this.fId, this.fName);
}
/// 重点关心这两个抽象类
@HostApi()// Flutter调用原生的方法写在下面 原生去实现
abstract class FlutterToNative {
// 通过id从原生获取信息
NativeBean loadNativeInfo(int id);
}
@FlutterApi()// 原生调用Flutter的方法 Flutter去实现
abstract class NativeToFlutter {
FlutterBean getFlutterInfo(int id);
}
这个类是我们编写的类,重点就是下方的两个注解的抽象类,需要我们定义通信方法。
创建完毕之后,执行.sh文件脚本即可生成上面4个文件。
4、Android实现Flutter调原生
将上面生成的java
文件粘贴到Android原生项目中,重新命名TestPluginPigeon。
并创建对应的实现类。
TestPlugin代码:
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
public class TestPlugin implements FlutterPlugin,TestPluginPigeon.FlutterToNative {
/// 绑定
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
///注册
TestPluginPigeon.FlutterToNative.setup(binding.getBinaryMessenger(),this);
}
/// 解绑
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
}
@NonNull
@Override
public TestPluginPigeon.NativeBean loadNativeInfo(@NonNull Long id) {
// 原生实现这个方法
TestPluginPigeon.NativeBean nativeBean = new TestPluginPigeon.NativeBean();
nativeBean.setId(0L);
nativeBean.setName("");
return nativeBean;
}
}
将TestPlugin注册到FLutter引擎中,这里我使用了flutter_boost
进行注册。(flutter引擎注册插件)
在Flutter中调用原生方法,将生成的pigeon_out拷贝到lib目录下,
在需要的地方直接调用,
FlutterToNative().loadNativeInfo(id).then((value) {
});
至此,FLutter调用原生Android完毕。
5、Android实现原生调Flutter
流程差不多,只不过反过来了,
首先在Flutter进行注册绑定,上面的test_plugin
就是我们需要实现的原生调用Flutter的方法。
/// 这里实现原生调用的方法
class TestPlugin implements NativeToFlutter {
@override
FlutterBean getFlutterInfo(int id) {
return FlutterBean(fId: 0, fName: '');
}
}
在初始化Flutter模块时注册TestPlugin,
NativeToFlutter.setup(TestPlugin());
原生调用这个方法:
首先我们在绑定的时候获取实体类,
public static TestPluginPigeon.NativeToFlutter nativeToFlutter;
/// 绑定
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
///注册
TestPluginPigeon.FlutterToNative.setup(binding.getBinaryMessenger(),this);
nativeToFlutter = new TestPluginPigeon.NativeToFlutter(binding.getBinaryMessenger());
}
在需要的地方调用,
TestPlugin.nativeToFlutter.getFlutterInfo(id, flutterBean -> {
/// 调用Flutter方法 获取返回值
});
自此,Android调用Flutter结束。
上面的通信都是同步的,如果需要异步在方法体上注解@aysnc
,用法大同小异,只是返回结果是异步返回。
@async
FlutterBean getFlutterInfo(int id);
iOS待补充
小结
通过查看生成的代码我们可以知道pigeon
生成的代码可以发现是基于BasicMessageChannel
实现的,我们只需要关心传输的具体数据,生成接口,实现接口即可,不需要关心维护具体的变量方法名等,对后续的维护成本有了极大的降低。