Flutter 官方嘗試放只「鴿子」來簡化Native插件開發

Flutter 在原生插件的開發上默認是須要開發者重複地寫模版代碼來接入,而近期 Flutter 團隊最近發佈了一個 package: pub.flutter-io.cn/packages/pi… , 主要是用來解決和優化 native 插件開發上 platform channel 相關的問題。java

該項目目前處於實驗性階段。android

該項目主要經過 Dart 腳本去自動生成通用的模板代碼,項目剛剛發佈測試因此也相對簡陋,而官方表示 pigeon 僅僅用於生成 Flutter 和宿主平臺的模版代碼,沒有任何運行時的要求,因此也不須要擔憂引入的衝突。ios

接入

集成 pigeon 首先須要在 dev_dependencies 引入 pigeon 依賴。git

dev_dependencies:
  flutter_test:
    sdk: flutter
  pigeon: ^0.1.0-experimental.3
複製代碼

以後在項目內建立一個 dart 文件,按照官方提供的建議咱們在項目根目錄建立了一個 pigeons 的目錄,而後建立一個 message.dart 文件。github

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() 註解標示了通訊對象和接口,以後咱們只須要執行以下命令,就能夠生成對應代碼到工程中。api

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"
複製代碼

如上所示命令行:bash

  • 經過 --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" 包名路徑下,以後就能夠開始正式接入。app

Android

首先看 Android 項目,在生成的 Pigeon.java 中包含了 Api 接口用於開發者實現交互邏輯,同時開發者能夠經過 SearchRequest 獲取 dart 發送過來的請求,經過 SearchReply 返回數據給 dart 。async

因此在 MainActivity 中經過實現 Api 接口就能夠完成數據交互,以下代碼所示:ide

  • 經過繼承 Pigeon.Api 實現了 MyApi 對象;
  • search 方法中經過 request.getQuery() 獲取 dart 的請求數據,而且經過 Pigeon.SearchReplysetResult 返回 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.hpigeon.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 去通訊,而且 SearchReplySearchRequest 也是按照咱們起初建立的 message.dart 中的對象去生成。

而對於 message.dart 官方目前也有一些要求,好比:

  • 該文件不能包含任何方法或函數定義。
  • 數據類型須要時 platform channel 支持的。
  • Api必須是一個「抽象類」,可使用「HostApi()」或 FlutterApi() 做爲元數據。
  • Api類的方法聲明應該有一個參數和一個返回 其類型在文件中定義的值。

經過這套規則,在實現原生插件時咱們能夠少些不少重複代碼,固然上述是直接在 Flutter App 工程中集成接入 pigeon ,正常流程應該是在插件工程中去使用。

同時官方也表示 pigeon 目前是實驗性的,將來可能會被刪除或者出現 Api 變更,Flutter 也 歡迎你們試一下在 GitHub 上提供反饋:github.com/flutter/pac…

資源推薦

相關文章
相關標籤/搜索