flutter 插件之 pigeon - 与宿主平台通信
Pigeon
Pigeon is a code generator tool to make communication between Flutter and the host platform type-safe, easier and faster.
Pigeon 是一个代码生成工具,让 Flutter 与宿主平台更简单、更快捷且类型安全地通信。非常类似于:Protocol Buffer
Pigeon 支持在 IOS 平台生成 Object-C 代码,在 Android 平台生成 Java 代码
插件地址:https://pub.flutter-io.cn/packages/pigeon
仓库地址:https://github.com/flutter/packages/tree/master/packages/pigeon/pigeons
示例地址:https://github.com/gaaclarke/pigeon_plugin_example
下面介绍 Pigeon(1.0.18) 使用方式(官方示例):
1. 创建插件工程,并安装 Pigeon
flutter create --template=plugin --platforms=android,ios -i swift -a kotlin day08_pigeon
通过 plugin 模板创建的项目中:
1. 有一个 example 文件夹,里面可以添加插件使用示例代码,方便测试插件
2. 在 pubspec.yaml 文件中,指定了各个平台真实实现的类名信息
1 2 3 4 5 6 7 8 | flutter: plugin: platforms: android: package: com.example.day08_pigeon pluginClass: Day08PigeonPlugin ios: pluginClass: Day08PigeonPlugin |
因为 Pigeon 是一个代码生成工具,并不需要运行时支持,所以只需要在 dev_dependencies 中添加
2. 添加协议
在项目的根目录中添加 pigeons 目录,并在里面添加需要宿主平台支持的 API,命名为 messages.dart,该文件为通信协议文件
这里参考示例,获取自定义宿主平台版本号为例:
1 2 3 4 5 6 7 8 9 10 | import 'package:pigeon/pigeon.dart' ; class MyVersion { String? myVersionResult; } @HostApi() abstract class ExampleApi { MyVersion getMyPlatformVersionResult(); } |
3. 运行 flutter pub run pigeon 生成代码
可以手写命令行,也可以参考示例中的方法,建立一个 run_pigeon.sh 文件,把命令写在文件中,当 API 更新后,再运行这个文件就行
当命令执行完成后,会在 .sh 文件中配置的位置,创建相应的 java 和 object-c 代码
备注:windows 平台下无法直接运行 .sh 文件,可通过 git bash 来运行
1 2 3 4 5 6 7 8 | flutter pub run pigeon \ --input pigeons/messages.dart \ --dart_out lib/messages.dart \ --objc_header_out ios/Classes/messages.h \ --objc_source_out ios/Classes/messages.m \ --objc_prefix FLT \ --java_out android/src/main/java/com/example/day08_pigeon/Messages.java \ --java_package "com.example.day08_pigeon" |
4. 实现宿主平台的 API
以 Android 平台为例,当 run_pigeon.sh 文件执行后,在项目中的 android/src/main 中,生成了 Java 文件 Messages.java,位置以 .sh 中 java_out 配置项为准
在 Java 文件中,会生成一个 public interface ExampleApi 接口,即在 messages.dart 中被标记为 @HostApi() 的抽象类,该接口为同名的协议接口
同时,在项目中的 android/src/main 中,生成了 Kotlin 文件,Day08PigeonPlugin.kt,该文件为与 Android 平台通信类
该类默认继承自 FlutterPlugin, MethodCallHandler
可在该类中直接添加协议接口实现(ExampleApi),也可以其它方式,比如创建新类来统一实现协议方法
这里以直接添加实现接口为例,添加 ExampleApi,并实现接口的所有方法和属性(由协议 messages.dart 定义)
同时,在该类的 FlutterPlugin 接口的 onAttachedToEngine,onDetachedFromEngine 方法中,通过调用 setup 方法来绑定 flutter 引擎具体调用的协议实现类对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | package com.example.day08_pigeon import androidx.annotation.NonNull /// 导入生成的 Java 文件中的包 import com.example.day08_pigeon.Messages.MyVersion import com.example.day08_pigeon.Messages.ExampleApi import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result /** Day08PigeonPlugin */ class Day08PigeonPlugin: FlutterPlugin, MethodCallHandler, ExampleApi { /// The MethodChannel that will the communication between Flutter and native Android /// /// This local reference serves to register the plugin with the Flutter Engine and unregister it /// when the Flutter Engine is detached from the Activity private lateinit var channel : MethodChannel override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { channel = MethodChannel(flutterPluginBinding.binaryMessenger, "day08_pigeon" ) channel.setMethodCallHandler( this ) /// 绑定 ExampleApi.setup(flutterPluginBinding.binaryMessenger, this ) } override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { if (call.method == "getPlatformVersion" ) { result.success( "Android ${android.os.Build.VERSION.RELEASE}" ) } else { result.notImplemented() } } override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { channel.setMethodCallHandler( null ) /// 解绑 ExampleApi.setup(binding.binaryMessenger, null ) } /// 协议实现 override fun getMyPlatformVersionResult(): MyVersion { val myVersion = MyVersion() myVersion.myVersionResult = "123.456.789" return myVersion } } |
5. 在 example 中添加测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import 'dart:async' ; import 'dart:io' ; import 'package:flutter/services.dart' ; import 'messages.dart' ; class Day08Pigeon { static const MethodChannel _channel = MethodChannel( 'day08_pigeon' ); static Future<MyVersion> get myPlatformVersionResult async { if (Platform.isAndroid || Platform.isIOS) { var exampleApi = ExampleApi(); return await exampleApi.getMyPlatformVersionResult(); } throw PlatformException(code: 'not suport ${Platform.operatingSystem}' ); } static Future<String?> get platformVersion async { final String? version = await _channel.invokeMethod( 'getPlatformVersion' ); return version; } } |
在 example 的 main.dart 中添加测试代码
1 2 3 4 5 6 7 8 9 | try { var result = await Day08Pigeon.myPlatformVersionResult; var version = result.myVersionResult; if (kDebugMode) { print( 'my version = $version' ); } } on PlatformException { platformVersion = 'Failed to get myPlatformVersionResult.' ; } |
完成!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!