上篇文章,Flutter Channel通信原理我们一起学习了Flutter Channel通信原理, 知道了, 一个消息从Flutter代码发出, 到c++流转, 再派发到iOS、Android平台。这篇文章, 我们一起来探讨OS是如何接收Flutter消息的。
回顾
由上篇文章分析, 可知, c++调用platform_message_router_.HandlePlatformMessage(std::move(message))
将消息发送给了iOS平台。其中很重要的一个知识点是, 在PlatformMessageRouter
类中的SetMessageHandler
, iOS平台定义了一个FlutterBinaryMessageHandler
回调来通信。 那么, iOS平台是如何接收消息呢? 我们一起探究源码。
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
中的SetMessageHandler
。 FlutterBasicMessageChannel
各提供了两种遍历构造器方法、两种初始化方法。
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
是订立的一个协议。
// 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
。
@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
也遵守并实现了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
协议。
@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
复制代码
JPushPlugin.h文件
/// 遵守FlutterPlugin协议
@interface JPushPlugin : NSObject<FlutterPlugin>
@property FlutterMethodChannel *channel;
@end
复制代码
@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
存储到PlatformMessageRouter
的message_handlers_
中- 当有
dart
通过invokeMethod
方法调用原生方法的时候,就会跟进channel
取出对应的handler
- 执行
handler
, 使原生代码setMethodCallHandler
的回调执行 - 然后, 使用
Plugin
传进来的delegate
将调用信息回调到handleMethodCall
方法上 - 由于
delegate
是遵守FlutterPlugin
协议的,所以只要在有类实现FlutterPlugin
的- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
方法就可以处理来自dart
的方法调用