当前位置: 首页 > 工具软件 > Pigeon > 使用案例 >

Flutter之pigeon

申炳
2023-12-01

资源

pigeon: ^1.0.17
packages/packages/pigeon
Flutter官方推荐插件开发辅助工具-Pigeon

安装

dart pub add pigeon

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  pigeon: ^1.0.7
  ...

步骤

1. 创建一个messages.dart模版文件

messages.dart

import 'package:pigeon/pigeon.dart';

class Book {
  String? title;
  String? author;
}

@HostApi()
abstract class BookApi {
  List<Book?> search(String keyword);
}

使用命令创建文件

./flutter pub run pigeon --input lib/messages.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/top/ovo/flutterame/Test.java --java_package "top.ovo.flutterame"

自动生成的文件

IOS生成的文件

pigeon.h

// Autogenerated from Pigeon (v1.0.17), do not edit directly.
// See also: https://pub.dev/packages/pigeon
#import <Foundation/Foundation.h>
@protocol FlutterBinaryMessenger;
@protocol FlutterMessageCodec;
@class FlutterError;
@class FlutterStandardTypedData;

NS_ASSUME_NONNULL_BEGIN

@class Book;

@interface Book : NSObject
+ (instancetype)makeWithTitle:(nullable NSString *)title
    author:(nullable NSString *)author;
@property(nonatomic, copy, nullable) NSString * title;
@property(nonatomic, copy, nullable) NSString * author;
@end

/// The codec used by BookApi.
NSObject<FlutterMessageCodec> *BookApiGetCodec(void);

@protocol BookApi
- (nullable NSArray<Book *> *)searchKeyword:(NSString *)keyword error:(FlutterError *_Nullable *_Nonnull)error;
@end

extern void BookApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSObject<BookApi> *_Nullable api);

NS_ASSUME_NONNULL_END

pigeon.m

// Autogenerated from Pigeon (v1.0.17), do not edit directly.
// See also: https://pub.dev/packages/pigeon
#import "pigeon.h"
#import <Flutter/Flutter.h>

#if !__has_feature(objc_arc)
#error File requires ARC to be enabled.
#endif

static NSDictionary<NSString *, id> *wrapResult(id result, FlutterError *error) {
  NSDictionary *errorDict = (NSDictionary *)[NSNull null];
  if (error) {
    errorDict = @{
        @"code": (error.code ? error.code : [NSNull null]),
        @"message": (error.message ? error.message : [NSNull null]),
        @"details": (error.details ? error.details : [NSNull null]),
        };
  }
  return @{
      @"result": (result ? result : [NSNull null]),
      @"error": errorDict,
      };
}
static id GetNullableObject(NSDictionary* dict, id key) {
  id result = dict[key];
  return (result == [NSNull null]) ? nil : result;
}


@interface Book ()
+ (Book *)fromMap:(NSDictionary *)dict;
- (NSDictionary *)toMap;
@end

@implementation Book
+ (instancetype)makeWithTitle:(nullable NSString *)title
    author:(nullable NSString *)author {
  Book* pigeonResult = [[Book alloc] init];
  pigeonResult.title = title;
  pigeonResult.author = author;
  return pigeonResult;
}
+ (Book *)fromMap:(NSDictionary *)dict {
  Book *pigeonResult = [[Book alloc] init];
  pigeonResult.title = GetNullableObject(dict, @"title");
  pigeonResult.author = GetNullableObject(dict, @"author");
  return pigeonResult;
}
- (NSDictionary *)toMap {
  return [NSDictionary dictionaryWithObjectsAndKeys:(self.title ? self.title : [NSNull null]), @"title", (self.author ? self.author : [NSNull null]), @"author", nil];
}
@end

@interface BookApiCodecReader : FlutterStandardReader
@end
@implementation BookApiCodecReader
- (nullable id)readValueOfType:(UInt8)type 
{
  switch (type) {
    case 128:     
      return [Book fromMap:[self readValue]];
    
    default:    
      return [super readValueOfType:type];
    
  }
}
@end

@interface BookApiCodecWriter : FlutterStandardWriter
@end
@implementation BookApiCodecWriter
- (void)writeValue:(id)value 
{
  if ([value isKindOfClass:[Book class]]) {
    [self writeByte:128];
    [self writeValue:[value toMap]];
  } else 
{
    [super writeValue:value];
  }
}
@end

@interface BookApiCodecReaderWriter : FlutterStandardReaderWriter
@end
@implementation BookApiCodecReaderWriter
- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data {
  return [[BookApiCodecWriter alloc] initWithData:data];
}
- (FlutterStandardReader *)readerWithData:(NSData *)data {
  return [[BookApiCodecReader alloc] initWithData:data];
}
@end

NSObject<FlutterMessageCodec> *BookApiGetCodec() {
  static dispatch_once_t sPred = 0;
  static FlutterStandardMessageCodec *sSharedObject = nil;
  dispatch_once(&sPred, ^{
    BookApiCodecReaderWriter *readerWriter = [[BookApiCodecReaderWriter alloc] init];
    sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter];
  });
  return sSharedObject;
}


void BookApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSObject<BookApi> *api) {
  {
    FlutterBasicMessageChannel *channel =
      [FlutterBasicMessageChannel
        messageChannelWithName:@"dev.flutter.pigeon.BookApi.search"
        binaryMessenger:binaryMessenger
        codec:BookApiGetCodec()];
    if (api) {
      NSCAssert([api respondsToSelector:@selector(searchKeyword:error:)], @"BookApi api (%@) doesn't respond to @selector(searchKeyword:error:)", api);
      [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
        NSArray *args = message;
        NSString *arg_keyword = args[0];
        FlutterError *error;
        NSArray<Book *> *output = [api searchKeyword:arg_keyword error:&error];
        callback(wrapResult(output, error));
      }];
    }
    else {
      [channel setMessageHandler:nil];
    }
  }
}

Android生成的文件

Pigeon.java

// Autogenerated from Pigeon (v1.0.17), do not edit directly.
// See also: https://pub.dev/packages/pigeon

package top.ovo.flutterame;

import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MessageCodec;
import io.flutter.plugin.common.StandardMessageCodec;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

/** Generated class from Pigeon. */
@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"})
public class Pigeon {

  /** Generated class from Pigeon that represents data sent in messages. */
  public static class Book {
    private @Nullable String title;
    public @Nullable String getTitle() { return title; }
    public void setTitle(@Nullable String setterArg) {
      this.title = setterArg;
    }

    private @Nullable String author;
    public @Nullable String getAuthor() { return author; }
    public void setAuthor(@Nullable String setterArg) {
      this.author = setterArg;
    }

    public static class Builder {
      private @Nullable String title;
      public @NonNull Builder setTitle(@Nullable String setterArg) {
        this.title = setterArg;
        return this;
      }
      private @Nullable String author;
      public @NonNull Builder setAuthor(@Nullable String setterArg) {
        this.author = setterArg;
        return this;
      }
      public @NonNull Book build() {
        Book pigeonReturn = new Book();
        pigeonReturn.setTitle(title);
        pigeonReturn.setAuthor(author);
        return pigeonReturn;
      }
    }
    @NonNull Map<String, Object> toMap() {
      Map<String, Object> toMapResult = new HashMap<>();
      toMapResult.put("title", title);
      toMapResult.put("author", author);
      return toMapResult;
    }
    static @NonNull Book fromMap(@NonNull Map<String, Object> map) {
      Book pigeonResult = new Book();
      Object title = map.get("title");
      pigeonResult.setTitle((String)title);
      Object author = map.get("author");
      pigeonResult.setAuthor((String)author);
      return pigeonResult;
    }
  }
  private static class BookApiCodec extends StandardMessageCodec {
    public static final BookApiCodec INSTANCE = new BookApiCodec();
    private BookApiCodec() {}
    @Override
    protected Object readValueOfType(byte type, ByteBuffer buffer) {
      switch (type) {
        case (byte)128:         
          return Book.fromMap((Map<String, Object>) readValue(buffer));
        
        default:        
          return super.readValueOfType(type, buffer);
        
      }
    }
    @Override
    protected void writeValue(ByteArrayOutputStream stream, Object value)     {
      if (value instanceof Book) {
        stream.write(128);
        writeValue(stream, ((Book) value).toMap());
      } else 
{
        super.writeValue(stream, value);
      }
    }
  }

  /** Generated interface from Pigeon that represents a handler of messages from Flutter.*/
  public interface BookApi {
    List<Book> search(String keyword);

    /** The codec used by BookApi. */
    static MessageCodec<Object> getCodec() {
      return BookApiCodec.INSTANCE;
    }

    /** Sets up an instance of `BookApi` to handle messages through the `binaryMessenger`. */
    static void setup(BinaryMessenger binaryMessenger, BookApi api) {
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.BookApi.search", getCodec());
        if (api != null) {
          channel.setMessageHandler((message, reply) -> {
            Map<String, Object> wrapped = new HashMap<>();
            try {
              ArrayList<Object> args = (ArrayList<Object>)message;
              String keywordArg = (String)args.get(0);
              if (keywordArg == null) {
                throw new NullPointerException("keywordArg unexpectedly null.");
              }
              List<Book> output = api.search(keywordArg);
              wrapped.put("result", output);
            }
            catch (Error | RuntimeException exception) {
              wrapped.put("error", wrapError(exception));
            }
            reply.reply(wrapped);
          });
        } else {
          channel.setMessageHandler(null);
        }
      }
    }
  }
  private static Map<String, Object> wrapError(Throwable exception) {
    Map<String, Object> errorMap = new HashMap<>();
    errorMap.put("message", exception.toString());
    errorMap.put("code", exception.getClass().getSimpleName());
    errorMap.put("details", "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception));
    return errorMap;
  }
}

 类似资料: