Flutter 在原生插件的開發(fā)上默認(rèn)是需要開發(fā)者重復(fù)地寫模版代碼來接入桐款,而近期 Flutter 團(tuán)隊(duì)最近發(fā)布了一個(gè) package: https://pub.flutter-io.cn/packages/pigeon , 主要是用來解決和優(yōu)化 native 插件開發(fā)上 platform channel 相關(guān)的問題夷恍。
該項(xiàng)目目前處于實(shí)驗(yàn)性階段魔眨。
該項(xiàng)目主要通過 Dart 腳本去自動(dòng)生成通用的模板代碼,項(xiàng)目剛剛發(fā)布測試所以也相對(duì)簡陋,而官方表示 pigeon 僅僅用于生成 Flutter 和宿主平臺(tái)的模版代碼遏暴,沒有任何運(yùn)行時(shí)的要求侄刽,所以也不需要擔(dān)心引入的沖突。
接入
集成 pigeon 首先需要在 dev_dependencies
引入 pigeon
依賴朋凉。
dev_dependencies:
flutter_test:
sdk: flutter
pigeon: ^0.1.0-experimental.3
之后在項(xiàng)目內(nèi)創(chuàng)建一個(gè) dart 文件州丹,按照官方提供的建議我們?cè)陧?xiàng)目根目錄創(chuàng)建了一個(gè) pigeons
的目錄,然后創(chuàng)建一個(gè) message.dart
文件杂彭。
import 'package:pigeon/pigeon_lib.dart';
class SearchRequest {
String query;
}
class SearchReply {
String result;
}
@HostApi()
abstract class Api {
SearchReply search(SearchRequest request);
}
如上代碼所示墓毒, message.dart
文件中通過 @HostApi()
注解標(biāo)示了通信對(duì)象和接口,之后我們只需要執(zhí)行如下命令亲怠,就可以生成對(duì)應(yīng)代碼到工程中所计。
flutter pub run pigeon --input pigeons/message.dart --dart_out lib/pigeon.dart --objc_header_out ios/Runner/pigeon.h --objc_source_out ios/Runner/pigeon.m --java_out android/app/src/main/java/com/shuyu/testpigeon/Pigeon.java --java_package "com.shuyu.testpigeon"
如上所示命令行:
- 通過
--input
引入了我們創(chuàng)建的message.dart
文件; - 通過
--dart_out
輸出了 dart 模板文件团秽; - 通過
--objc_header_out
和--objc_source_out
輸出了 object-c 文件主胧; - 通過
--java_out
輸出了 java 文件;
命令執(zhí)行后 dart 文件輸出到 lib
目錄下习勤, object-c 文件輸出到了 ios/Runner
目錄下讥裤,java 文件輸出到指定的 com.shuyu.testpigeon"
包名路徑下,之后就可以開始正式接入姻报。
Android
首先看 Android 項(xiàng)目己英,在生成的 Pigeon.java
中包含了 Api
接口用于開發(fā)者實(shí)現(xiàn)交互邏輯,同時(shí)開發(fā)者可以通過 SearchRequest
獲取 dart 發(fā)送過來的請(qǐng)求吴旋,通過 SearchReply
返回?cái)?shù)據(jù)給 dart 损肛。
所以在 MainActivity
中通過實(shí)現(xiàn) Api
接口就可以完成數(shù)據(jù)交互,如下代碼所示:
- 通過繼承
Pigeon.Api
實(shí)現(xiàn)了MyApi
對(duì)象荣瑟; - 在
search
方法中通過request.getQuery()
獲取 dart 的請(qǐng)求數(shù)據(jù)治拿,并且通過Pigeon.SearchReply
的setResult
返回String.format("Hi %s!", request.getQuery())
,在收到的 dart 文本之前加上Hi
并返回笆焰; - 最后通過
Pigeon.Api.setup(getFlutterView(), new MyApi());
就可以完成引用劫谅;
package com.shuyu.testpigeon;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
private class MyApi implements Pigeon.Api {
@Override
public Pigeon.SearchReply search(Pigeon.SearchRequest request) {
Pigeon.SearchReply reply = new Pigeon.SearchReply();
reply.setResult(String.format("Hi %s!", request.getQuery()));
return reply;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
Pigeon.Api.setup(getFlutterView(), new MyApi());
}
}
iOS
在 iOS 上首先要先把生成的 pigeon.h
和 pigeon.m
文件 link 到 Xcode 工程里,之后如下代碼所示在 AppDelegate.h
引入 Api
協(xié)議嚷掠。
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "pigeon.h"
@interface AppDelegate : FlutterAppDelegate<Api>
@end
如下代碼所示捏检,接下來在 AppDelegate.m
中實(shí)現(xiàn) search
接口,然后在收到的 dart 文本之前加上 Hi
并返回不皆,最后調(diào)用 ApiSetup
方法將完成注冊(cè)贯城。
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
FlutterViewController* controller =
(FlutterViewController*)self.window.rootViewController;
ApiSetup(controller.binaryMessenger, self);
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
-(SearchReply *)search:(SearchRequest*)input error:(FlutterError **)error {
SearchReply* result = [[SearchReply alloc] init];
result.result = [NSString stringWithFormat:@"%s%@","Hi ",input.query];
return result;
}
@end
Dart
如下代碼所示,最后在 Dart 代碼中霹娄,我們只需要通過 pigeon.dart
中的 Api
去調(diào)用 search
方法能犯,就可以完成 dart 到原生的通信邏輯鲫骗,最后在終端看到 Hi GSY
的輸出。
void _incrementCounter() async{
SearchRequest request = SearchRequest()..query = "GSY";
Api api = Api();
SearchReply reply = await api.search(request);
print("###### ${reply.result}");
}
我們可以看到在 igeon.dart
文件中其實(shí)就是通過 dev.flutter.pigeon.Api.search
標(biāo)示的 StandardMessageCodec
去通信踩晶,并且 SearchReply
和 SearchRequest
也是按照我們起初創(chuàng)建的 message.dart
中的對(duì)象去生成执泰。
而對(duì)于 message.dart
官方目前也有一些要求,比如:
- 該文件不能包含任何方法或函數(shù)定義渡蜻。
- 數(shù)據(jù)類型需要時(shí) platform channel 支持的坦胶。
- Api必須是一個(gè)“抽象類”,可以使用“HostApi()”或 FlutterApi() 作為元數(shù)據(jù)晴楔。
- Api類的方法聲明應(yīng)該有一個(gè)參數(shù)和一個(gè)返回
其類型在文件中定義的值顿苇。
通過這套規(guī)則,在實(shí)現(xiàn)原生插件時(shí)我們可以少些很多重復(fù)代碼税弃,當(dāng)然上述是直接在 Flutter App 工程中集成接入 pigeon
纪岁,正常流程應(yīng)該是在插件工程中去使用。
同時(shí)官方也表示 pigeon
目前是實(shí)驗(yàn)性的则果,未來可能會(huì)被刪除或者出現(xiàn) Api 變動(dòng)幔翰,F(xiàn)lutter 也 歡迎大家試一下在 GitHub 上提供反饋:https://github.com/flutter/packages,希望這只“鴿子”未來會(huì)有放飛的一天西壮。
資源推薦
- 本文 demo :https://gitee.com/CarGuo/test_pigeon
- Github :https://github.com/CarGuo
- 開源 Flutter 完整項(xiàng)目:https://github.com/CarGuo/GSYGithubAppFlutter
- 開源 Flutter 多案例學(xué)習(xí)型項(xiàng)目: https://github.com/CarGuo/GSYFlutterDemo
- 開源 Fluttre 實(shí)戰(zhàn)電子書項(xiàng)目:https://github.com/CarGuo/GSYFlutterBook
- 開源 React Native 項(xiàng)目:https://github.com/CarGuo/GSYGithubApp