iOS如何接收Platform Channel消息?

上篇文章,Flutter Channel通信原理我们一起学习了Flutter Channel通信原理, 知道了, 一个消息从Flutter代码发出, 到c++流转, 再派发到iOS、Android平台。这篇文章, 我们一起来探讨OS是如何接收Flutter消息的。

回顾

由上篇文章分析, 可知, c++调用platform_message_router_.HandlePlatformMessage(std::move(message))将消息发送给了iOS平台。其中很重要的一个知识点是, 在PlatformMessageRouter类中的SetMessageHandler, iOS平台定义了一个FlutterBinaryMessageHandler回调来通信。 那么, iOS平台是如何接收消息呢? 我们一起探究源码。

FlutterChannels.mm

iOS端接收消息的通道对应dart端也分为三种

  • Basic message channel: 支持字符串和半结构化的数据传递。双向传递。
  • Method channel: 支持方法调用,既可以从Flutter发平台发起方法调用,也可以从平台代码向Flutter发起调用。 可以双向传递。
  • Event channel: 支持数据流通信。

FlutterBasicMessageChannel

static NSString* const FlutterChannelBuffersChannel = @"dev.flutter/channel-buffers";

static void ResizeChannelBuffer(NSObject<FlutterBinaryMessenger>* binaryMessenger,
                                NSString* channel,
                                NSInteger newSize) {
  NSString* messageString = [NSString stringWithFormat:@"resize\r%@\r%@", channel, @(newSize)];
  NSData* message = [messageString dataUsingEncoding:NSUTF8StringEncoding];
  [binaryMessenger sendOnChannel:FlutterChannelBuffersChannel message:message];
}

static FlutterBinaryMessengerConnection SetMessageHandler(
    NSObject<FlutterBinaryMessenger>* messenger,
    NSString* name,
    FlutterBinaryMessageHandler handler,
    NSObject<FlutterTaskQueue>* taskQueue) {
  if (taskQueue) {
    NSCAssert([messenger respondsToSelector:@selector(setMessageHandlerOnChannel:
                                                            binaryMessageHandler:taskQueue:)],
              @"");
    return [messenger setMessageHandlerOnChannel:name
                            binaryMessageHandler:handler
                                       taskQueue:taskQueue];
  } else {
    return [messenger setMessageHandlerOnChannel:name binaryMessageHandler:handler];
  }
}

////////////////////////////////////////////////////////////////////////////////
@implementation FlutterBasicMessageChannel {
 /// 声明信使FlutterBinaryMessager(是订立的协议)成员变量_messenger
  NSObject<FlutterBinaryMessenger>* _messenger;
  NSString* _name;
  NSObject<FlutterMessageCodec>* _codec;
  FlutterBinaryMessengerConnection _connection;
  NSObject<FlutterTaskQueue>* _taskQueue;
}
+ (instancetype)messageChannelWithName:(NSString*)name
                       binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
  NSObject<FlutterMessageCodec>* codec = [FlutterStandardMessageCodec sharedInstance];
  return [FlutterBasicMessageChannel messageChannelWithName:name
                                            binaryMessenger:messenger
                                                      codec:codec];
}
+ (instancetype)messageChannelWithName:(NSString*)name
                       binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
                                 codec:(NSObject<FlutterMessageCodec>*)codec {
  return [[[FlutterBasicMessageChannel alloc] initWithName:name
                                           binaryMessenger:messenger
                                                     codec:codec] autorelease];
}

- (instancetype)initWithName:(NSString*)name
             binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
                       codec:(NSObject<FlutterMessageCodec>*)codec {
  self = [self initWithName:name binaryMessenger:messenger codec:codec taskQueue:nil];
  return self;
}

- (instancetype)initWithName:(NSString*)name
             binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
                       codec:(NSObject<FlutterMessageCodec>*)codec
                   taskQueue:(NSObject<FlutterTaskQueue>*)taskQueue {
  self = [super init];
  NSAssert(self, @"Super init cannot be nil");
  _name = [name retain];
  _messenger = [messenger retain];
  _codec = [codec retain];
  _taskQueue = [taskQueue retain];
  return self;
}

- (void)dealloc {
  [_name release];
  [_messenger release];
  [_codec release];
  [_taskQueue release];
  [super dealloc];
}

- (void)sendMessage:(id)message {
  [_messenger sendOnChannel:_name message:[_codec encode:message]];
}

- (void)sendMessage:(id)message reply:(FlutterReply)callback {
  FlutterBinaryReply reply = ^(NSData* data) {
    if (callback) {
      callback([_codec decode:data]);
    }
  };
  [_messenger sendOnChannel:_name message:[_codec encode:message] binaryReply:reply];
}

/// 通过setMessageHandler跟flutter通信
- (void)setMessageHandler:(FlutterMessageHandler)handler {
  if (!handler) {
    if (_connection > 0) {
      [_messenger cleanUpConnection:_connection];
      _connection = 0;
    } else {
      [_messenger setMessageHandlerOnChannel:_name binaryMessageHandler:nil];
    }
    return;
  }
  // Grab reference to avoid retain on self.
  NSObject<FlutterMessageCodec>* codec = _codec;
  FlutterBinaryMessageHandler messageHandler = ^(NSData* message, FlutterBinaryReply callback) {
    handler([codec decode:message], ^(id reply) {
      callback([codec encode:reply]);
    });
  };
  _connection = SetMessageHandler(_messenger, _name, messageHandler, _taskQueue);
}

- (void)resizeChannelBuffer:(NSInteger)newSize {
  ResizeChannelBuffer(_messenger, _name, newSize);
}

@end

复制代码

分析源码, 我们终于找到了, 上一章节中, PlatformMessageRouter.mm中的SetMessageHandlerFlutterBasicMessageChannel各提供了两种遍历构造器方法、两种初始化方法。

FlutterMethodChannel

封装外部传进来的方法、参数
////////////////////////////////////////////////////////////////////////////////
@implementation FlutterMethodCall
+ (instancetype)methodCallWithMethodName:(NSString*)method arguments:(id)arguments {
  return [[[FlutterMethodCall alloc] initWithMethodName:method arguments:arguments] autorelease];
}

- (instancetype)initWithMethodName:(NSString*)method arguments:(id)arguments {
  NSAssert(method, @"Method name cannot be nil");
  self = [super init];
  NSAssert(self, @"Super init cannot be nil");
  _method = [method retain];
  _arguments = [arguments retain];
  return self;
}

- (void)dealloc {
  [_method release];
  [_arguments release];
  [super dealloc];
}

- (BOOL)isEqual:(id)object {
  if (self == object) {
    return YES;
  }
  if (![object isKindOfClass:[FlutterMethodCall class]]) {
    return NO;
  }
  FlutterMethodCall* other = (FlutterMethodCall*)object;
  return [self.method isEqual:[other method]] &&
         ((!self.arguments && !other.arguments) || [self.arguments isEqual:other.arguments]);
}

- (NSUInteger)hash {
  return [self.method hash] ^ [self.arguments hash];
}
@end

NSObject const* FlutterMethodNotImplemented = [[NSObject alloc] init];

/// FlutterMethodChannel通道, 通过方法通信。
////////////////////////////////////////////////////////////////////////////////
@implementation FlutterMethodChannel {
  NSObject<FlutterBinaryMessenger>* _messenger;
  NSString* _name;
  NSObject<FlutterMethodCodec>* _codec;
  FlutterBinaryMessengerConnection _connection;
  NSObject<FlutterTaskQueue>* _taskQueue;
}

+ (instancetype)methodChannelWithName:(NSString*)name
                      binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
  NSObject<FlutterMethodCodec>* codec = [FlutterStandardMethodCodec sharedInstance];
  return [FlutterMethodChannel methodChannelWithName:name binaryMessenger:messenger codec:codec];
}

+ (instancetype)methodChannelWithName:(NSString*)name
                      binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
                                codec:(NSObject<FlutterMethodCodec>*)codec {
  return [[[FlutterMethodChannel alloc] initWithName:name binaryMessenger:messenger
                                               codec:codec] autorelease];
}

- (instancetype)initWithName:(NSString*)name
             binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
                       codec:(NSObject<FlutterMethodCodec>*)codec {
  self = [self initWithName:name binaryMessenger:messenger codec:codec taskQueue:nil];
  return self;
}
- (instancetype)initWithName:(NSString*)name
             binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
                       codec:(NSObject<FlutterMethodCodec>*)codec
                   taskQueue:(NSObject<FlutterTaskQueue>*)taskQueue {
  self = [super init];
  NSAssert(self, @"Super init cannot be nil");
  _name = [name retain];
  _messenger = [messenger retain];
  _codec = [codec retain];
  _taskQueue = [taskQueue retain];
  return self;
}

- (void)dealloc {
  [_name release];
  [_messenger release];
  [_codec release];
  [_taskQueue release];
  [super dealloc];
}

- (void)invokeMethod:(NSString*)method arguments:(id)arguments {
  FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:method
                                                                    arguments:arguments];
  NSData* message = [_codec encodeMethodCall:methodCall];
  [_messenger sendOnChannel:_name message:message];
}

- (void)invokeMethod:(NSString*)method arguments:(id)arguments result:(FlutterResult)callback {
  FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:method
                                                                    arguments:arguments];
  NSData* message = [_codec encodeMethodCall:methodCall];
  FlutterBinaryReply reply = ^(NSData* data) {
    if (callback) {
      callback((data == nil) ? FlutterMethodNotImplemented : [_codec decodeEnvelope:data]);
    }
  };
  [_messenger sendOnChannel:_name message:message binaryReply:reply];
}

/// 跟Flutter通信的回调。
- (void)setMethodCallHandler:(FlutterMethodCallHandler)handler {
  if (!handler) {
    if (_connection > 0) {
      [_messenger cleanUpConnection:_connection];
      _connection = 0;
    } else {
      [_messenger setMessageHandlerOnChannel:_name binaryMessageHandler:nil];
    }
    return;
  }
  // Make sure the block captures the codec, not self.
  NSObject<FlutterMethodCodec>* codec = _codec;
  FlutterBinaryMessageHandler messageHandler = ^(NSData* message, FlutterBinaryReply callback) {
    FlutterMethodCall* call = [codec decodeMethodCall:message];
    handler(call, ^(id result) {
      if (result == FlutterMethodNotImplemented) {
        callback(nil);
      } else if ([result isKindOfClass:[FlutterError class]]) {
        callback([codec encodeErrorEnvelope:(FlutterError*)result]);
      } else {
        callback([codec encodeSuccessEnvelope:result]);
      }
    });
  };
  _connection = SetMessageHandler(_messenger, _name, messageHandler, _taskQueue);
}

- (void)resizeChannelBuffer:(NSInteger)newSize {
  ResizeChannelBuffer(_messenger, _name, newSize);
}

@end

复制代码

FlutterMethodChannel通道跟Flutter通信, 先将外部传进来的方法名MethodName, 参数arguments:(id)封装成FlutterMethodCall对象。

FlutterEventChannel

#pragma mark - Event channel

NSObject const* FlutterEndOfEventStream = [[NSObject alloc] init];

////////////////////////////////////////////////////////////////////////////////
@implementation FlutterEventChannel {
  NSObject<FlutterBinaryMessenger>* _messenger;
  NSString* _name;
  NSObject<FlutterMethodCodec>* _codec;
  NSObject<FlutterTaskQueue>* _taskQueue;
  FlutterBinaryMessengerConnection _connection;
}
+ (instancetype)eventChannelWithName:(NSString*)name
                     binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
  NSObject<FlutterMethodCodec>* codec = [FlutterStandardMethodCodec sharedInstance];
  return [FlutterEventChannel eventChannelWithName:name binaryMessenger:messenger codec:codec];
}

+ (instancetype)eventChannelWithName:(NSString*)name
                     binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
                               codec:(NSObject<FlutterMethodCodec>*)codec {
  return [[[FlutterEventChannel alloc] initWithName:name binaryMessenger:messenger
                                              codec:codec] autorelease];
}

- (instancetype)initWithName:(NSString*)name
             binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
                       codec:(NSObject<FlutterMethodCodec>*)codec {
  return [self initWithName:name binaryMessenger:messenger codec:codec taskQueue:nil];
}

- (instancetype)initWithName:(NSString*)name
             binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
                       codec:(NSObject<FlutterMethodCodec>*)codec
                   taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue {
  self = [super init];
  NSAssert(self, @"Super init cannot be nil");
  _name = [name retain];
  _messenger = [messenger retain];
  _codec = [codec retain];
  _taskQueue = [taskQueue retain];
  return self;
}

- (void)dealloc {
  [_name release];
  [_codec release];
  [_messenger release];
  [_taskQueue release];
  [super dealloc];
}

static FlutterBinaryMessengerConnection SetStreamHandlerMessageHandlerOnChannel(
    NSObject<FlutterStreamHandler>* handler,
    NSString* name,
    NSObject<FlutterBinaryMessenger>* messenger,
    NSObject<FlutterMethodCodec>* codec,
    NSObject<FlutterTaskQueue>* taskQueue) {
  __block FlutterEventSink currentSink = nil;
  FlutterBinaryMessageHandler messageHandler = ^(NSData* message, FlutterBinaryReply callback) {
    FlutterMethodCall* call = [codec decodeMethodCall:message];
    if ([call.method isEqual:@"listen"]) {
      if (currentSink) {
        FlutterError* error = [handler onCancelWithArguments:nil];
        if (error) {
          NSLog(@"Failed to cancel existing stream: %@. %@ (%@)", error.code, error.message,
                error.details);
        }
      }
      currentSink = ^(id event) {
        if (event == FlutterEndOfEventStream) {
          [messenger sendOnChannel:name message:nil];
        } else if ([event isKindOfClass:[FlutterError class]]) {
          [messenger sendOnChannel:name message:[codec encodeErrorEnvelope:(FlutterError*)event]];
        } else {
          [messenger sendOnChannel:name message:[codec encodeSuccessEnvelope:event]];
        }
      };
      FlutterError* error = [handler onListenWithArguments:call.arguments eventSink:currentSink];
      if (error) {
        callback([codec encodeErrorEnvelope:error]);
      } else {
        callback([codec encodeSuccessEnvelope:nil]);
      }
    } else if ([call.method isEqual:@"cancel"]) {
      if (!currentSink) {
        callback(
            [codec encodeErrorEnvelope:[FlutterError errorWithCode:@"error"
                                                           message:@"No active stream to cancel"
                                                           details:nil]]);
        return;
      }
      currentSink = nil;
      FlutterError* error = [handler onCancelWithArguments:call.arguments];
      if (error) {
        callback([codec encodeErrorEnvelope:error]);
      } else {
        callback([codec encodeSuccessEnvelope:nil]);
      }
    } else {
      callback(nil);
    }
  };
  return SetMessageHandler(messenger, name, messageHandler, taskQueue);
}

- (void)setStreamHandler:(NSObject<FlutterStreamHandler>*)handler {
  if (!handler) {
    [_messenger cleanUpConnection:_connection];
    _connection = 0;
    return;
  }
  _connection =
      SetStreamHandlerMessageHandlerOnChannel(handler, _name, _messenger, _codec, _taskQueue);
}
@end

复制代码

总结一下, 跟上一篇文章Flutter Channel通信原理里的Flutter端一样, iOS端收、发消息也依赖信使FlutterBinaryMessenger

  • FlutterBasicMessageChannel: 使用setMessageHandler接收Flutter端消息。
  • FlutterMethodChannel: 使用setMethodCallHandler接收Flutter端消息。
  • FlutterEventChannel: 使用setStreamHandler接收Flutter端消息。

由此可见, iOS端接收消息, 重难点在信使FlutterBinaryMessenger的理解上。那么, 信使FlutterBinaryMessenger是怎样在iOS端实现消息的收、发操作呢?接下来, 我们一起探究。

信使FlutterBinaryMessenger

iOS上的信使FlutterBinaryMessenger是订立的一个协议。

协议文件FlutterBinaryMessenger.h

// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_FLUTTERBINARYMESSENGER_H_
#define FLUTTER_FLUTTERBINARYMESSENGER_H_

#import <Foundation/Foundation.h>

#import "FlutterMacros.h"

NS_ASSUME_NONNULL_BEGIN

typedef void (^FlutterBinaryReply)(NSData* _Nullable reply);

typedef void (^FlutterBinaryMessageHandler)(NSData* _Nullable message, FlutterBinaryReply reply);

typedef int64_t FlutterBinaryMessengerConnection;

@protocol FlutterTaskQueue;


FLUTTER_DARWIN_EXPORT
@protocol FlutterBinaryMessenger <NSObject>
/// TODO(gaaclarke): Remove optional when macos supports Background Platform Channels.
@optional
- (NSObject<FlutterTaskQueue>*)makeBackgroundTaskQueue;

- (FlutterBinaryMessengerConnection)
    setMessageHandlerOnChannel:(NSString*)channel
          binaryMessageHandler:(FlutterBinaryMessageHandler _Nullable)handler
                     taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue;

@required
/**
 * Sends a binary message to the Flutter side on the specified channel, expecting
 * no reply.
 *
 * @param channel The channel name.
 * @param message The message.
 */
- (void)sendOnChannel:(NSString*)channel message:(NSData* _Nullable)message;

/**
 * Sends a binary message to the Flutter side on the specified channel, expecting
 * an asynchronous reply.
 *
 * @param channel The channel name.
 * @param message The message.
 * @param callback A callback for receiving a reply.
 */
- (void)sendOnChannel:(NSString*)channel
              message:(NSData* _Nullable)message
          binaryReply:(FlutterBinaryReply _Nullable)callback;

/**
 * Registers a message handler for incoming binary messages from the Flutter side
 * on the specified channel.
 *
 * Replaces any existing handler. Use a `nil` handler for unregistering the
 * existing handler.
 *
 * @param channel The channel name.
 * @param handler The message handler.
 * @return An identifier that represents the connection that was just created to the channel.
 */
- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(NSString*)channel
                                          binaryMessageHandler:
                                              (FlutterBinaryMessageHandler _Nullable)handler;

/**
 * Clears out a channel's message handler if that handler is still the one that
 * was created as a result of
 * `setMessageHandlerOnChannel:binaryMessageHandler:`.
 *
 * @param connection The result from `setMessageHandlerOnChannel:binaryMessageHandler:`.
 */
- (void)cleanUpConnection:(FlutterBinaryMessengerConnection)connection;
@end
NS_ASSUME_NONNULL_END
#endif  // FLUTTER_FLUTTERBINARYMESSENGER_H_

复制代码

iOS平台上信使FlutterBinaryMessenger的实现类是FlutterBinaryMessengerRelay, 它遵守并实现了FlutterBinaryMessenger协议。

FlutterBinaryMessengerRelayr.h

#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"

#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
FLUTTER_DARWIN_EXPORT
#endif
@interface FlutterBinaryMessengerRelay : NSObject <FlutterBinaryMessenger>
@property(nonatomic, assign) NSObject<FlutterBinaryMessenger>* parent;
- (instancetype)initWithParent:(NSObject<FlutterBinaryMessenger>*)parent;
@end
复制代码
  • 声明了一个协议属性parent
  • 定义了一个初始化方法nitWithParent:(NSObject<FlutterBinaryMessenger>*)parent

FlutterBinaryMessengerRelay.mm

// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h"

#include "flutter/fml/logging.h"

@implementation FlutterBinaryMessengerRelay
#pragma mark - FlutterBinaryMessenger

- (instancetype)initWithParent:(NSObject<FlutterBinaryMessenger>*)parent {
  self = [super init];
  if (self != nil) {
    self.parent = parent;
  }
  return self;
}

- (void)sendOnChannel:(NSString*)channel message:(NSData*)message {
  if (self.parent) {
    [self.parent sendOnChannel:channel message:message binaryReply:nil];
  } else {
    FML_LOG(WARNING) << "Communicating on a dead channel.";
  }
}

- (void)sendOnChannel:(NSString*)channel
              message:(NSData*)message
          binaryReply:(FlutterBinaryReply)callback {
  if (self.parent) {
    [self.parent sendOnChannel:channel message:message binaryReply:callback];
  } else {
    FML_LOG(WARNING) << "Communicating on a dead channel.";
  }
}

- (NSObject<FlutterTaskQueue>*)makeBackgroundTaskQueue {
  if (self.parent) {
    return [self.parent makeBackgroundTaskQueue];
  } else {
    return nil;
  };
}

- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(NSString*)channel
                                          binaryMessageHandler:
                                              (FlutterBinaryMessageHandler)handler {
  if (self.parent) {
    return [self.parent setMessageHandlerOnChannel:channel binaryMessageHandler:handler];
  } else {
    FML_LOG(WARNING) << "Communicating on a dead channel.";
    return -1;
  }
}

- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(NSString*)channel
                                          binaryMessageHandler:(FlutterBinaryMessageHandler)handler
                                                     taskQueue:
                                                         (NSObject<FlutterTaskQueue>*)taskQueue {
  if (self.parent) {
    return [self.parent setMessageHandlerOnChannel:channel
                              binaryMessageHandler:handler
                                         taskQueue:taskQueue];
  } else {
    FML_LOG(WARNING) << "Communicating on a dead channel.";
    return -1;
  }
}

- (void)cleanUpConnection:(FlutterBinaryMessengerConnection)connection {
  if (self.parent) {
    return [self.parent cleanUpConnection:connection];
  } else {
    FML_LOG(WARNING) << "Communicating on a dead channel.";
  }
}

@end

复制代码

FlutterBinaryMessengerRelay做为信使FlutterBinaryMessenger协议的实现着, 遵守并实现了信使FlutterBinaryMessenger协议。

源码分析到这里, 我们明白了消息通过信使FlutterBinaryMessenger传到了iOS平台的mm层面。那么在iOS原生平台messenger是怎样使用的呢? 带着问题, 我们发现, FlutterBinaryMessenger信使在iOS原生平台都是作为参数进行传递的,只有FlutterPluginRegistrar这个协议里定义了这个接口

AppDelegatge

FlutterPluginRegistry

@protocol FlutterPluginRegistry <NSObject>

- (**nullable** NSObject<FlutterPluginRegistrar>*)registrarForPlugin:(NSString*)pluginKey;

- (**BOOL**)hasPlugin:(NSString*)pluginKey;

- (**nullable** NSObject*)valuePublishedByPlugin:(NSString*)pluginKey;

@end
复制代码

FlutterPluginRegistry是订立的协议。

FlutterPluginRegistrar

FlutterPluginRegistrar也是订立的协议。

FlutterBinaryMessenger信使在iOS原生平台都是作为参数进行传递的,只有FlutterPluginRegistrar这个协议里定义了这个接口

@protocol** FlutterPluginRegistrar <NSObject>

- (NSObject<FlutterBinaryMessenger>*)messenger;

- (NSObject<FlutterTextureRegistry>*)textures;

- (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
                     withId:(NSString*)factoryId;

- (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
                              withId:(NSString*)factoryId
    gestureRecognizersBlockingPolicy:
        (FlutterPlatformViewGestureRecognizersBlockingPolicy)gestureRecognizersBlockingPolicy;

- (void)publish:(NSObject*)value;

- (void)addMethodCallDelegate:(NSObject<FlutterPlugin>*)delegate
                      channel:(FlutterMethodChannel*)channel;

- (void)addApplicationDelegate:(NSObject<FlutterPlugin>*)delegate;

- (NSString*)lookupKeyForAsset:(NSString*)asset;

- (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package;
@end
复制代码

FlutterPlugin

FlutterPlugin也是个协议。


+ (**void**)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar;

复制代码

我们继续探索

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    /// 注册
  [GeneratedPluginRegistrant registerWithRegistry:self];
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end
复制代码

FlutterAppDelegate

原来在iOS平台的启动文件, 通过GeneratedPluginRegistrant类统一注册了所有插件, 并且将当前AppDelegate实例对象做为参数传了进去, 由此可知, AppDelegate肯定遵守并实现了FlutterPluginRegistry协议。我们去AppDelegate看看:

@interface FlutterAppDelegate: UIResponder <UIApplicationDelegate, FlutterPluginRegistry, FlutterAppLifeCycleProvider>
@property**(**strong**, **nonatomic**) UIWindow* window;
@end
复制代码

有源码可以知道, FlutterAppDelegate遵守并实现了FlutterPluginRegistry协议。所以FlutterAppDelegate类或其子类必须实现FlutterPluginRegistry定义的接口(**nullable** NSObject<FlutterPluginRegistrar>*)registrarForPlugin:(NSString*)pluginKey

FlutterAppDelegate.mm源码

@implementation FlutterAppDelegate {
  FlutterPluginAppLifeCycleDelegate* _lifeCycleDelegate;
}

- (instancetype)init {
  if (self = [super init]) {
    _lifeCycleDelegate = [[FlutterPluginAppLifeCycleDelegate alloc] init];
  }
  return self;
}

/// 返回根控制器
- (FlutterViewController*)rootFlutterViewController {
  if (_rootFlutterViewControllerGetter != nil) {
    return _rootFlutterViewControllerGetter();
  }
  UIViewController* rootViewController = _window.rootViewController;
  if ([rootViewController isKindOfClass:[FlutterViewController class]]) {
    return (FlutterViewController*)rootViewController;
  }
  return nil;
}

......

/// 我们重点关注遵守并实现的协议 FlutterPluginRegistry
#pragma mark - FlutterPluginRegistry methods. All delegating to the rootViewController

- (NSObject<FlutterPluginRegistrar>*)registrarForPlugin:(NSString*)pluginKey {
  FlutterViewController* flutterRootViewController = [self rootFlutterViewController];
  if (flutterRootViewController) {
  /// 真正注册插件, 是FlutterViewController做的。
    return [[flutterRootViewController pluginRegistry] registrarForPlugin:pluginKey];
  }
  return nil;
}

- (BOOL)hasPlugin:(NSString*)pluginKey {
  FlutterViewController* flutterRootViewController = [self rootFlutterViewController];
  if (flutterRootViewController) {
    return [[flutterRootViewController pluginRegistry] hasPlugin:pluginKey];
  }
  return false;
}

- (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey {
  FlutterViewController* flutterRootViewController = [self rootFlutterViewController];
  if (flutterRootViewController) {
    return [[flutterRootViewController pluginRegistry] valuePublishedByPlugin:pluginKey];
  }
  return nil;
}

复制代码

FlutterAppDelegate.mm文件, 很清楚地知道, FlutterAppDelegate遵守并实现了FlutterPluginRegistry协议。并且, 发现一个惊天秘密, 真正注册插件的是FlutterViewController类。

  • FlutterAppDelegate通过FlutterViewController注册插件。惊天秘密。

FlutterViewController

那么, FlutterViewController又是怎样注册插件的呢?

我们去FlutterViewController源码看看。

FlutterViewController.h文件

FlutterViewController.mm文件

FlutterViewController也遵守并实现了FlutterPluginRegistry协议。

FlutterViewController.h文件:

@interface FlutterViewController : UIViewController <FlutterTextureRegistry, FlutterPluginRegistry>
@end
复制代码

FlutterViewController.mm文件:

@implementation FlutterViewController {
  std::unique_ptr<fml::WeakPtrFactory<FlutterViewController>> _weakFactory;
  fml::scoped_nsobject<FlutterEngine> _engine;
}

......

- (FlutterEngine*)engine {
  return _engine.get();
}


- (void)viewDidLoad {
  TRACE_EVENT0("flutter", "viewDidLoad");

  if (_engine && _engineNeedsLaunch) {
    // Register internal plugins before starting the engine.
    [self addInternalPlugins];

    [_engine.get() launchEngine:nil libraryURI:nil entrypointArgs:nil];
    [_engine.get() setViewController:self];
    _engineNeedsLaunch = NO;
  }

  /// _engine.get()去attachView了
  if ([_engine.get() viewController] == self) {
    [_engine.get() attachView];
  }

  if (@available(iOS 13.4, *)) {
    _pointerInteraction.reset([[UIPointerInteraction alloc] initWithDelegate:self]);
    [self.view addInteraction:_pointerInteraction];

    _panGestureRecognizer.reset(
        [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(scrollEvent:)]);
    _panGestureRecognizer.get().allowedScrollTypesMask = UIScrollTypeMaskAll;
    _panGestureRecognizer.get().allowedTouchTypes = @[ @(UITouchTypeIndirectPointer) ];
    [_flutterView.get() addGestureRecognizer:_panGestureRecognizer.get()];
  }

  [super viewDidLoad];
}

/// _engine也遵守了FlutterPluginRegistry协议。
/// 获取引擎_engine对象
- (id<FlutterPluginRegistry>)pluginRegistry {
  return _engine;
}

#pragma mark - FlutterPluginRegistry

/// 由引擎_engine对象注册插件。
- (NSObject<FlutterPluginRegistrar>*)registrarForPlugin:(NSString*)pluginKey {
  return [_engine.get() registrarForPlugin:pluginKey];
}

- (BOOL)hasPlugin:(NSString*)pluginKey {
  return [_engine.get() hasPlugin:pluginKey];
}

- (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey {
  return [_engine.get() valuePublishedByPlugin:pluginKey];
}

- (void)presentViewController:(UIViewController*)viewControllerToPresent
                     animated:(BOOL)flag
                   completion:(void (^)(void))completion {
  self.isPresentingViewControllerAnimating = YES;
  [super presentViewController:viewControllerToPresent
                      animated:flag
                    completion:^{
                      self.isPresentingViewControllerAnimating = NO;
                      if (completion) {
                        completion();
                      }
                    }];
}

@end
复制代码
  • FlutterViewController中遵守并实现了FlutterPluginRegistry协议,
  • registrarForPlugin方法中, 由引擎_engine对象执行[_engine.get() registrarForPlugin:pluginKey]注册插件的。

FlutterEngine

那么, FlutterEngine也遵守并实现了FlutterPluginRegistry协议。

FlutterEngine.mm


@interface FlutterEngine () <FlutterIndirectScribbleDelegate,
                             FlutterTextInputDelegate,
                             FlutterBinaryMessenger>
// Maintains a dictionary of plugin names that have registered with the engine.  Used by
// FlutterEngineRegistrar to implement a FlutterPluginRegistrar.
@property(nonatomic, readonly) NSMutableDictionary* pluginPublications;
@property(nonatomic, readonly) NSMutableDictionary<NSString*, FlutterEngineRegistrar*>* registrars;

@property(nonatomic, readwrite, copy) NSString* isolateId;
@property(nonatomic, copy) NSString* initialRoute;
@property(nonatomic, retain) id<NSObject> flutterViewControllerWillDeallocObserver;
@end

@implementation FlutterEngine {
  fml::scoped_nsobject<FlutterDartProject> _dartProject;
  std::shared_ptr<flutter::ThreadHost> _threadHost;
  std::unique_ptr<flutter::Shell> _shell;
  NSString* _labelPrefix;
  std::unique_ptr<fml::WeakPtrFactory<FlutterEngine>> _weakFactory;

  fml::WeakPtr<FlutterViewController> _viewController;
  fml::scoped_nsobject<FlutterObservatoryPublisher> _publisher;

  std::shared_ptr<flutter::FlutterPlatformViewsController> _platformViewsController;
  flutter::IOSRenderingAPI _renderingApi;
  std::shared_ptr<flutter::ProfilerMetricsIOS> _profiler_metrics;
  std::shared_ptr<flutter::SamplingProfiler> _profiler;
  
  /// 信使FlutterBinaryMessengerRelay类
  FlutterBinaryMessengerRelay* _binaryMessenger;
  std::unique_ptr<flutter::ConnectionCollection> _connections;
}

/// 遵守并实现FlutterPluginRegistry协议

#pragma mark - FlutterPluginRegistry

- (NSObject<FlutterPluginRegistrar>*)registrarForPlugin:(NSString*)pluginKey {
/// 在这里创建了FlutterPlugin引擎对象
  NSAssert(self.pluginPublications[pluginKey] == nil, @"Duplicate plugin key: %@", pluginKey);
  self.pluginPublications[pluginKey] = [NSNull null];
  FlutterEngineRegistrar* result = [[FlutterEngineRegistrar alloc] initWithPlugin:pluginKey
  flutterEngine:self];
  self.registrars[pluginKey] = result;
  return [result autorelease];
}

- (BOOL)hasPlugin:(NSString*)pluginKey {
  return _pluginPublications[pluginKey] != nil;
}

- (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey {
  return _pluginPublications[pluginKey];

@end
复制代码

其实就是拿到外界传进来的pluginKey, 创建一个遵守FlutterPluginRegistrar协议的FlutterEngineRegistrar对象并返回。

信使信使FlutterBinaryMessengerRelay类遵守了FlutterBinaryMessenger协议。

FlutterEngineRegistrar

@interface FlutterEngineRegistrar : NSObject <FlutterPluginRegistrar>
@property(nonatomic, assign) FlutterEngine* flutterEngine;
- (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(FlutterEngine*)flutterEngine;
@end


@implementation FlutterEngineRegistrar {
  NSString* _pluginKey;
}

- (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(FlutterEngine*)flutterEngine {
  self = [super init];
  NSAssert(self, @"Super init cannot be nil");
  _pluginKey = [pluginKey copy];
  _flutterEngine = flutterEngine;
  return self;
}

- (void)dealloc {
  [_pluginKey release];
  [super dealloc];
}

# 遵守并实现 FlutterPluginRegistrar 协议

- (NSObject<FlutterBinaryMessenger>*)messenger {
  return _flutterEngine.binaryMessenger;
}

- (NSObject<FlutterTextureRegistry>*)textures {
  return _flutterEngine;
}

- (void)publish:(NSObject*)value {
  _flutterEngine.pluginPublications[_pluginKey] = value;
}

/// delegate: 遵守并实现了FlutterPlugin协议的delegate对象
- (void)addMethodCallDelegate:(NSObject<FlutterPlugin>*)delegate
                      channel:(FlutterMethodChannel*)channel {
  [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
  /// 收到消息后, 执行delegate里面实现的handleMethodCall result方法。
    [delegate handleMethodCall:call result:result];
  }];
}

- (void)addApplicationDelegate:(NSObject<FlutterPlugin>*)delegate {
  id<UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
  if ([appDelegate conformsToProtocol:@protocol(FlutterAppLifeCycleProvider)]) {
    id<FlutterAppLifeCycleProvider> lifeCycleProvider =
        (id<FlutterAppLifeCycleProvider>)appDelegate;
    [lifeCycleProvider addApplicationLifeCycleDelegate:delegate];
  }
}

- (NSString*)lookupKeyForAsset:(NSString*)asset {
  return [_flutterEngine lookupKeyForAsset:asset];
}

- (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package {
  return [_flutterEngine lookupKeyForAsset:asset fromPackage:package];
}

- (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
                     withId:(NSString*)factoryId {
  [self registerViewFactory:factory
                                withId:factoryId
      gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager];
}

- (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
                              withId:(NSString*)factoryId
    gestureRecognizersBlockingPolicy:
        (FlutterPlatformViewGestureRecognizersBlockingPolicy)gestureRecognizersBlockingPolicy {
  [_flutterEngine platformViewsController]->RegisterViewFactory(factory, factoryId,
                                                                gestureRecognizersBlockingPolicy);
}

@end

复制代码

一路分析下来, 我们终于明白了

  • GeneratedPluginRegistrant类的+ (**void**)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;方法中, registry就是FlutterEngine返回的遵守了FlutterPluginRegistrar协议的FlutterEngineRegistrar对象。
  • 信使 FlutterBinaryMessengerRelay就是遵守FlutterBinaryMessenger协议的对象。

JPushPlugin插件

GeneratedPluginRegistrant

那么在iOS原生层面是怎样注册并实现一个plugin的呢? 我们用一个plugin来看看。

GeneratedPluginRegistrant源码如下:

@implementation GeneratedPluginRegistrant

/// registry: 就是`FlutterEngine`返回的遵守了`FlutterPluginRegistrar`协议的`FlutterEngineRegistrar`对象。

+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
  [JmessageFlutterPlugin registerWithRegistrar:[registry registrarForPlugin:@"JmessageFlutterPlugin"]];
  [JPushPlugin registerWithRegistrar:[registry registrarForPlugin:@"JPushPlugin"]];
}
@end
复制代码

极光推送插件jpush_flutter

JPushPlugin.h文件

JPushPlugin.h文件
/// 遵守FlutterPlugin协议
@interface JPushPlugin : NSObject<FlutterPlugin>
@property FlutterMethodChannel *channel;
@end
复制代码

JPushPlugin.m文件

@implementation JPushPlugin {
    NSDictionary *_launchNotification;
    NSDictionary *_completeLaunchNotification;
    BOOL _isJPushDidLogin;
    JPAuthorizationOptions notificationTypes;
}

/// 传进来的registrar: 是个遵守FlutterPluginRegistrar协议的对象

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    getRidResults = @[].mutableCopy;
    
    /// 拿到registrar对象绑定的信使
    FlutterMethodChannel* channel = [FlutterMethodChannel
                                     methodChannelWithName:@"jpush"
                                     binaryMessenger:[registrar messenger]];
    JPushPlugin* instance = [[JPushPlugin alloc] init];
    instance.channel = channel;
    
    /// 注册
    [registrar addMethodCallDelegate:instance channel:channel];
}
@end
复制代码

JPushPlugin插件, 我们可以看到, JPushPlugin遵守并实现了FlutterPlugin协议。

传进来的registrar: 是个遵守FlutterPluginRegistrar协议的对象。

总结如下:

  • channel名来注册methodCallHandler, 最终handler存储到PlatformMessageRoutermessage_handlers_
  • 当有dart通过invokeMethod方法调用原生方法的时候,就会跟进channel取出对应的handler
  • 执行handler, 使原生代码setMethodCallHandler的回调执行
  • 然后, 使用Plugin传进来的delegate将调用信息回调到handleMethodCall方法上
  • 由于delegate是遵守FlutterPlugin协议的,所以只要在有类实现FlutterPlugin- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result方法就可以处理来自dart的方法调用

参考资料

FlutterChannels.mm

FlutterBinaryMessenger.h协议

FlutterBinaryMessengerRelay.mm文件

极光推送插件jpush_flutter

FlutterViewController.h文件

FlutterAppDelegate.mm文件

FlutterEngine.mm文件

猜你喜欢

转载自juejin.im/post/7035278408292499464