Flutter 在原生外掛的開發上預設是需要開發者重複地寫模版程式碼來接入,而近期 Flutter 團隊最近釋出了一個 package: pub.flutter-io.cn/packages/pi… , 主要是用來解決和優化 native 外掛開發上 platform channel 相關的問題。
該專案目前處於實驗性階段。
該專案主要通過 Dart 指令碼去自動生成通用的模板程式碼,專案剛剛釋出測試所以也相對簡陋,而官方表示 pigeon 僅僅用於生成 Flutter 和宿主平臺的模版程式碼,沒有任何執行時的要求,所以也不需要擔心引入的衝突。
接入
整合 pigeon 首先需要在 dev_dependencies
引入 pigeon
依賴。
dev_dependencies:
flutter_test:
sdk: flutter
pigeon: ^0.1.0-experimental.3
複製程式碼
之後在專案內建立一個 dart 檔案,按照官方提供的建議我們在專案根目錄建立了一個 pigeons
的目錄,然後建立一個 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()
註解標示了通訊物件和介面,之後我們只需要執行如下命令,就可以生成對應程式碼到工程中。
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
引入了我們建立的message.dart
檔案; - 通過
--dart_out
輸出了 dart 模板檔案; - 通過
--objc_header_out
和--objc_source_out
輸出了 object-c 檔案; - 通過
--java_out
輸出了 java 檔案;
命令執行後 dart 檔案輸出到 lib
目錄下, object-c 檔案輸出到了 ios/Runner
目錄下,java 檔案輸出到指定的 com.shuyu.testpigeon"
包名路徑下,之後就可以開始正式接入。
Android
首先看 Android 專案,在生成的 Pigeon.java
中包含了 Api
介面用於開發者實現互動邏輯,同時開發者可以通過 SearchRequest
獲取 dart 傳送過來的請求,通過 SearchReply
返回資料給 dart 。
所以在 MainActivity
中通過實現 Api
介面就可以完成資料互動,如下程式碼所示:
- 通過繼承
Pigeon.Api
實現了MyApi
物件; - 在
search
方法中通過request.getQuery()
獲取 dart 的請求資料,並且通過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
協議。
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "pigeon.h"
@interface AppDelegate : FlutterAppDelegate<Api>
@end
複製程式碼
如下程式碼所示,接下來在 AppDelegate.m
中實現 search
介面,然後在收到的 dart 文字之前加上 Hi
並返回,最後呼叫 ApiSetup
方法將完成註冊。
#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
去呼叫 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
檔案中其實就是通過 dev.flutter.pigeon.Api.search
標示的 StandardMessageCodec
去通訊,並且 SearchReply
和 SearchRequest
也是按照我們起初建立的 message.dart
中的物件去生成。
而對於 message.dart
官方目前也有一些要求,比如:
- 該檔案不能包含任何方法或函式定義。
- 資料型別需要時 platform channel 支援的。
- Api必須是一個“抽象類”,可以使用“HostApi()”或 FlutterApi() 作為後設資料。
- Api類的方法宣告應該有一個引數和一個返回 其型別在檔案中定義的值。
通過這套規則,在實現原生外掛時我們可以少些很多重複程式碼,當然上述是直接在 Flutter App 工程中整合接入 pigeon
,正常流程應該是在外掛工程中去使用。
同時官方也表示 pigeon
目前是實驗性的,未來可能會被刪除或者出現 Api 變動,Flutter 也 歡迎大家試一下在 GitHub 上提供反饋:github.com/flutter/pac…
資源推薦
- 本文 demo :gitee.com/CarGuo/test…
- Github :github.com/CarGuo
- 開源 Flutter 完整專案:github.com/CarGuo/GSYG…
- 開源 Flutter 多案例學習型專案: github.com/CarGuo/GSYF…
- 開源 Fluttre 實戰電子書專案:github.com/CarGuo/GSYF…
- 開源 React Native 專案:github.com/CarGuo/GSYG…