指定ios_debug_sim_unopt引擎

1.首要新建一个flutter工程,找到ios目录下在Generated文件中指定调试的引擎

// ios配置文件指定引擎
//FLUTTER_ENGINE=/Users/xxx/engine/src
//LOCAL_ENGINE=ios_debug_sim_unopt
// ios配置文件指定引擎

当然前提是这儿已经运用GN构建好了

Flutter进阶-引擎源码调试
2.此时运行iOS工程,设置断点
Flutter进阶-引擎源码调试
点击屏幕触发断点,盯梢这些断点能够找到-[FlutterViewController touchesBegan:withEvent:]这个办法,找到上面的ios_debug_sim_unopt的目录,翻开flutter_engine工程,在FlutterViewController.m文件中找到了这个办法。
Flutter进阶-引擎源码调试
Flutter进阶-引擎源码调试

这样通过调试debug的引擎能够一步一步来盯梢办法的完成,为咱们更好的理解Flutter供给了一种办法。

Flutter Channel底层原理探究

Flutter作为一个灵敏的UI框架,无论是iOS渠道上的OC或Swift, 仍是安卓渠道上的Java或Kotlin都能够通过Platform Channel机制来与Flutter进行通讯。需求留意的是Platform Channel不依赖代码而成,而是建立在音讯传递的方式上。实际上,它的作业模式和原理十分类似于基于二进制协议开发的网络服务

iOS channel原理

Flutter供给了三种Channel用作Flutter与iOS原生渠道之间的数据传递

Flutter进阶-引擎源码调试

FlutterMethodChannel(name: "one", binaryMessenger: self.flutterVc as! FlutterBinaryMessenger)
FlutterBasicMessageChannel(name: "messageChannel", binaryMessenger: self.flutterVc.binaryMessenger)

三种channel分别带来不同的效果,但是设计上大同小异,都有以下几个成员变量

  • name: channel称号,作为每个channel的仅有标志。在flutter运用中,通常会存在多个Platform Channel,这些channel之间便是通过仅有标志name来区别。例如FlutterMethodChannel建议办法调用时,就需求咱们为MethodChannel指定对应的标志name
  • messenger:音讯信使(BinaryMessenger)用作音讯的发送和接收的东西,主要担任flutter与原生之间的彼此通讯,尽管flutter中存在三种不同的Channel,但是对应的交流东西都是BinaryMessenger

Flutter进阶-引擎源码调试

在创立一个channel后,不论是通过设置代理仍是通过setHandle回调来进行音讯处理,最终都会为该channel绑定一个FlutterBinaryMessengerHandler,而且以channel的name作为key,保存在一个map中。当接收到发送音讯之后,会根据音讯中携带的channel称号取出对应的FlutterBinaryMessengerHandler,交给BinaryMessenger处理,在ios渠道上BinaryMessenger是一个名为FlutterBinaryMessenger协议

FlutterMethodChanneladdMethodCallDelegate:channel:为例 addMethodCallDelegate:channel: -> setMethodCallHandler:handler -> setMessageHandlerOnChannel:binaryMessageHandler: -> PlatformMessageRouter::SetMessageHandler

void PlatformMessageRouter::SetMessageHandler(const std::string& channel,
                                              FlutterBinaryMessageHandler handler) {
    message_handlers_.erase(channel);
    if (handler) {
        message_handlers_[channel] =
            fml::ScopedBlock<FlutterBinaryMessageHandler>{handler, fml::OwnershipPolicy::Retain};
    }
}

通过这个办法链也验证了上面说的每一个FlutterBinaryMessengerHandler的key值都是channel的name

  • Codec(编解码器):在channel中,messenger携带的数据需求在Dart层和Native层传输,所以就需求一种与渠道无关的数据协议,既能支撑图片又能支撑文件等资源。因此官方选用了二进制字节省作为数据传输协议。二进制字节省:发送方需求把数据编写成二进制数据,接收方再把数据解码成原始数据,而担任编解码操作的便是Codec。在flutter中有两种Codec

FlutterMessageCodec

FlutterMessageCodec:对message进行编解码,用于二进制与根底数据之间的编解码,其间FlutterBasicMessenger选用的便是这个Codec,在flutter中,MessageCodec有多种完成

@protocol FlutterMessageCodec
+ (instancetype)sharedInstance;
// 将指定类型的message编码为二进制数据
- (NSData* _Nullable)encode:(id _Nullable)message;
// 将二进制数据NSData解码成指定类型
- (id _Nullable)decode:(NSData* _Nullable)message;
@end

Flutter进阶-引擎源码调试

  • FlutterStandardMessageCodec:是BasicMessage Channel默认运用的编解码器,底层是用FlutterStandardReaderWriter完成的,用于数据类型和二进制之间的编解码。支撑根底数据类型包含(bool/char/string/double/float/int/long/short/array/dictionary)以及二进制数据
  • FlutterBinaryCodec:用于二进制数据与二进制数据之间的编解码,在完成上仅仅原封不动的将接收到的二进制数据回来
  • FlutterStringCodec:用于字符串与二进制数据之间的编解码,字符串选用utf-8编码格局
  • FlutterJSONMessageCodec:用于数据类型与二进制数据之间的编解码,支撑根底数据类型,在iOS端运用NSJSONSerialization作为序列化的东西

FlutterMethodCodec

  • FlutterMethodCodec用于二进制数据与办法调用FlutterMethodCall和回来成果之间的编解码,主要是用在FlutterMethodChannelFlutterEventChannel
@protocol FlutterMethodCodec
+ (instancetype)sharedInstance;
// 将FlutterMethodCall编码为二进制NSData
- (NSData*)encodeMethodCall:(FlutterMethodCall*)methodCall;
// 将二进制NSData解码为FlutterMethodCall
- (FlutterMethodCall*)decodeMethodCall:(NSData*)methodCall;
// 将正常响应成果result编码为二进制
- (NSData*)encodeSuccessEnvelope:(id _Nullable)result;
// 将错误响应提示编码为二进制NSData
- (NSData*)encodeErrorEnvelope:(FlutterError*)error;
// 将二进制数据NSData解码,失利回来 FlutterError
- (id _Nullable)decodeEnvelope:(NSData*)envelope;
@end

FlutterMethodCall代表从Flutter端建议的办法调用,办法调用包含:办法名、参数以及回来成果。因此和FlutterMessageCodec比较,FlutterMethodCodec中多了两个处理调用成果的办法 当时在FlutterMethodCodec有两种完成

  • FlutterJSONMethodCodec:在将FlutterMethodCall目标进行编码时,会首要将该目标转换成JSON目标
@interface FlutterJSONMethodCodec : NSObject <FlutterMethodCodec>
- (NSData*)encodeMethodCall:(FlutterMethodCall*)call {
  return [[FlutterJSONMessageCodec sharedInstance] encode:@{
    @"method" : call.method,
    @"args" : [self wrapNil:call.arguments],
  }];
}

在编码调用成果时,会将其转化为一个数组,调用成功为[result],调用失利为[code, message, details]

- (NSData*)encodeSuccessEnvelope:(id)result {
  return [[FlutterJSONMessageCodec sharedInstance] encode:@[ [self wrapNil:result] ]];
}
- (NSData*)encodeErrorEnvelope:(FlutterError*)error {
  return [[FlutterJSONMessageCodec sharedInstance] encode:@[
    error.code,
    [self wrapNil:error.message],
    [self wrapNil:error.details],
  ]];
}
  • FlutterStandardMethodCodec:是FlutterMethodCodec的默认完成,当其编码在将FlutterMethodCall目标进行编码时,会将Methodargs依次运用FlutterStandardReaderWriter进行编码,然后写成二进制数据。

深入编解码器原理

上面咱们说过FlutterStandardMessageCodeFlutterStandardMethodCodec都是运用了FlutterStandardReaderWriter进行编码,那么咱们来看下FlutterStandardMethodCodec的界说

+ (instancetype)sharedInstance {
  static id _sharedInstance = nil;
  if (!_sharedInstance) {
    FlutterStandardReaderWriter* readerWriter =
        [[[FlutterStandardReaderWriter alloc] init] autorelease];
    _sharedInstance = [[FlutterStandardMethodCodec alloc] initWithReaderWriter:readerWriter];
  }
  return _sharedInstance;
}

要点分析FlutterStandardReaderWriter怎样来编解码的

@implementation FlutterStandardReaderWriter
- (FlutterStandardWriter*)writerWithData:(NSMutableData*)data {
  return [[[FlutterStandardWriter alloc] initWithData:data] autorelease];
}
- (FlutterStandardReader*)readerWithData:(NSData*)data {
  return [[[FlutterStandardReader alloc] initWithData:data] autorelease];
}
@end
// 15个枚举值用来标识不同的数据类型,0是null,3表示Int32类型
// 在向NSData写入指定类型的数据时,需求首要写入标志位,然后紧接着写入值
// 在从NSData读取数据时,首要读取类型标志,然后读取详细的值
typedef NS_ENUM(NSInteger, FlutterStandardField) {
  FlutterStandardFieldNil,
  FlutterStandardFieldTrue,
  FlutterStandardFieldFalse,
  FlutterStandardFieldInt32,
  FlutterStandardFieldInt64,
  FlutterStandardFieldIntHex,
  FlutterStandardFieldFloat64,
  FlutterStandardFieldString,
  FlutterStandardFieldUInt8Data,
  FlutterStandardFieldInt32Data,
  FlutterStandardFieldInt64Data,
  FlutterStandardFieldFloat64Data,
  FlutterStandardFieldList,
  FlutterStandardFieldMap,
  FlutterStandardFieldFloat32Data,
};

readerWithData:从NSData中读取value值 writerWithData:用于将value值写入到NSData中

Handler音讯处理

Flutter中界说了一套handler用于处理通过Codec解码后的音讯,在运用channel时,需求为其设置对应的handler,本质上便是为其注册一个对应的FlutterBinaryMessageHandler,二进制数据被FlutterBinaryMessageHandler进行处理,首要运用Codec进行解码操作,然后再分发给详细的Handler进行处理。与三种Platform Channel相对应,Flutter中也界说了三种Handler

  • FlutterMessageHandler用于处理字符串或许半结构化音讯
typedef void (^FlutterMessageHandler)(id _Nullable message, FlutterReply callback);
  • FlutterMethodCallHandler用于处理办法调用
  • FlutterStreamHandler用于事情流通讯,通常是用于渠道主动向Flutter发送事情通知
@protocol FlutterStreamHandler
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
                                       eventSink:(FlutterEventSink)events;
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments;
@end

onListenWithArguments:eventSink:当Flutter端开端监听渠道事情时,会向渠道建议一次MethodCall其间办法名为listen,也便是最终会调用FlutterStreamHandler中的这个办法,其间eventSink的参数可用于向Flutter发送事情 onCancelWithArguments:当Flutter端中止监听渠道事情时,会向渠道建议一次MethodCall其间办法名为cancel,也便是最终会调用FlutterStreamHandler中的这个办法,在该办法中通常需求销毁一些无用的资源