Pigeon是Flutter官方为了解决Flutter和Native互相调用过于繁琐,所发布的一款插件。使用Pigeon开发插件,过程会变得非常简单。
本文档编写时间为2022年4月24日,使用Flutter版本为 stable 2.10.4 Pigeon版本为3.0.3
新建plugin并引入pigeon
flutter create --template=plugin --platforms android,ios flutter_pigeon_plugin
在pubspec.yaml
中加入以下代码
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^1.0.0
# 将下方代码加入对应位置
pigeon:
执行flutter pub get
编写pigeon文件
项目内新建文件夹pigeons
,并在其中新建message.dart
(此为示例,实际开发中文件名及文件夹随意)
编写message.dart
// pigeons/message.dart
import 'package:pigeon/pigeon.dart';
class F2NMessage{
String? msg;
}
class N2FMessage{
String? msg2;
}
@HostApi()
abstract class FlutterMessage{
void flutterSendMessage(F2NMessage msg);
}
@FlutterApi()
abstract class NativeMessage{
void nativeSendMessage(N2FMessage msg);
}
在demo中,我新建了一个flutter发往native的方法flutterSendMessage
,参数为F2NMessage
。新建了一个native发往flutter的方法nativeSendMessage
,参数为N2FMessage
。
新建一个sh脚本(作者为Mac系统,windows系统请自行编写)run_pigeon.sh
# run_pigeon.sh
mkdir -p android/src/main/java/com/example/flutter_pigeon_plugin
flutter pub run pigeon \
--input pigeons/message.dart \
--dart_out lib/message.dart \
--objc_header_out ios/Classes/Message.h \
--objc_source_out ios/Classes/Message.m \
--java_out android/src/main/java/com/example/flutter_pigeon_plugin/Message.java \
--java_package "com.example.flutter_pigeon_plugin"
由于我新建的是kt/swift插件,所以需要新建android/src/main/java/com/example/flutter_pigeon_plugin
文件夹用于存放自动生成的Message.java文件,pigeon目前仅支持java和objc类型,不过由于kt/swift与java/objc均可互相调用,所以没有任何影响。
编写插件
上一步sh执行完成后,插件自动在lib下生成了对应的message.dart
文件,我们这时候可以在lib/flutter_pigeon_plugin.dart
中开始编写插件。
// lib/flutter_pigeon_plugin.dart
import 'package:flutter_pigeon_plugin/message.dart';
class FlutterPigeonPlugin extends NativeMessage {
static final FlutterMessage _flutterMessage = FlutterMessage();
factory FlutterPigeonPlugin() => _getInstance();
static FlutterPigeonPlugin get instance => _getInstance();
static FlutterPigeonPlugin? _instance = null;
static FlutterPigeonPlugin _getInstance() {
_instance ??= FlutterPigeonPlugin._internal();
NativeMessage.setup(_instance);
return _instance!;
}
FlutterPigeonPlugin._internal();
void sendMessage() {
F2NMessage message = F2NMessage();
message.msg = "这是一条从Flutter发往Native的消息";
_flutterMessage.flutterSendMessage(message);
}
@override
void nativeSendMessage(N2FMessage msg) {
print("收到了Native发来的消息:${msg.msg2}");
}
}
从以上代码中,我们可以了解到如何向Native发送消息,及如何接收Native发来的消息。
编写iOS端代码
由于插件使用swift开发,故仅提供swift类型插件的相关说明,Objective-C可以参阅swift代码自行修改
run_pigeon.sh
文件执行完成后,ios/Classes
文件夹中已经自行生成大量代码。首先我们需要新建flutter_pigeon_plugin.h
文件,方便让swift文件自动引入我们新建的代码
// ios/Classes/flutter_pigeon_plugin.h
#import "Message.h"
编写SwiftFlutterPigeonPlugin.swift
文件
// ios/Classes/SwiftFlutterPigeonPlugin.swift
import Flutter
import UIKit
public class SwiftFlutterPigeonPlugin: NSObject, FlutterPlugin,FlutterMessage {
public func flutterSendMsg(_ msg: F2NMessage, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) {
print("收到来自于Flutter的消息"+msg.msg!)
let message:N2FMessage = N2FMessage.make(withMsg2: "iOS返回的消息")
nativeMessage.nativeSendMsg(message, completion: {e in})
}
public var nativeMessage:NativeMessage!
public static func register(with registrar: FlutterPluginRegistrar) {
let messenger: FlutterBinaryMessenger = registrar.messenger()
let api = SwiftFlutterPigeonPlugin.init()
FlutterMessageSetup(messenger, api)
api.nativeMessage = NativeMessage(binaryMessenger: messenger)
}
}
编写example中的main.dart
看一下效果
import 'package:flutter/material.dart';
import 'package:flutter_pigeon_plugin/flutter_pigeon_plugin.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late FlutterPigeonPlugin _flutterPigeonPlugin;
@override
void initState() {
super.initState();
_flutterPigeonPlugin = FlutterPigeonPlugin();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: TextButton(
child: Text("点击这里向native发送消息"),
onPressed: () {
_flutterPigeonPlugin.sendMessage();
}),
),
),
);
}
}
点击屏幕中的按钮,控制台打印返回消息
截屏2022-04-24 10.17.42.png编写Android端代码
由于插件使用kt开发,故仅提供kt类型插件的相关说明,java可以参阅kt代码自行修改
run_pigeon.sh
文件执行完成后,src/main/java/com/example/flutter_pigeon_plugin
文件夹中已经自行生成大量代码。
直接开始编辑FlutterPigeonPlugin.kt
// src/main/kotlin/com/example/flutter_pigeon_plugin/FlutterPigeonPlugin.kt
package com.example.flutter_pigeon_plugin
import android.util.Log
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
/** FlutterPigeonPlugin */
class FlutterPigeonPlugin : FlutterPlugin, Message.FlutterMessage {
lateinit var nativeMessage: Message.NativeMessage
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
Message.FlutterMessage.setup(flutterPluginBinding.binaryMessenger, this)
nativeMessage = Message.NativeMessage(flutterPluginBinding.binaryMessenger)
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
}
override fun flutterSendMessage(msg: Message.F2NMessage) {
Log.d("FlutterPigeonPlugin", msg.msg.toString())
var respMsg: Message.N2FMessage = Message.N2FMessage()
respMsg.msg2 = "Android的返回值"
nativeMessage.nativeSendMessage(respMsg, {})
}
}
点击屏幕中的按钮,控制台打印消息
截屏2022-04-24 10.18.29.png
网友评论