美文网首页Android开发Android开发经验谈Android技术知识
Flutter 官方尝试放只“鸽子”来简化Native插件开发

Flutter 官方尝试放只“鸽子”来简化Native插件开发

作者: 恋猫月亮 | 来源:发表于2020-03-18 17:11 被阅读0次

    Flutter 在原生插件的开发上默认是需要开发者重复地写模版代码来接入,而近期 Flutter 团队最近发布了一个 package: https://pub.flutter-io.cn/packages/pigeon , 主要是用来解决和优化 native 插件开发上 platform channel 相关的问题。

    该项目目前处于实验性阶段。

    image

    该项目主要通过 Dart 脚本去自动生成通用的模板代码,项目刚刚发布测试所以也相对简陋,而官方表示 pigeon 仅仅用于生成 Flutter 和宿主平台的模版代码,没有任何运行时的要求,所以也不需要担心引入的冲突。

    image

    接入

    集成 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.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 上提供反馈:https://github.com/flutter/packages,希望这只“鸽子”未来会有放飞的一天。

    资源推荐

    image

    相关文章

      网友评论

        本文标题:Flutter 官方尝试放只“鸽子”来简化Native插件开发

        本文链接:https://www.haomeiwen.com/subject/vqscyhtx.html