| 1.嵌入Flutter 
 先创建ios工程
 
 我们先创建NativeDemo ios工程然后,导入cocopad通过配置pod文件来引入Flutter 框架。
 
 
 创建flutter_module工程,用于原生引入调用:复制代码flutter_app_path = '../flutter_module'load File.join(flutter_app_path,'.iOS','Flutter','podhelper.rb')platform :ios, '11.0'post_install do |installer|  flutter_post_install(installer)endtarget 'NativeDemo' do  install_all_flutter_pods(flutter_app_path)  use_frameworks!end
 在来看ios原生怎样嵌入Flutter页面:
 
 然后我们在看flutter_module工程代码:复制代码#import <Flutter/Flutter.h>@property(nonatomic, strong) FlutterEngine * flutterEngine;@property(nonatomic, strong) FlutterViewController* flutterVc;@property(nonatomic, strong) FlutterBasicMessageChannel* msgChannel;- (IBAction)pushFlutter:(id)sender {   //告诉Flutter显示one_page    FlutterMethodChannel * methodChannel = [FlutterMethodChannel methodChannelWithName:@"one_page" binaryMessenger:self.flutterVc];    [methodChannel invokeMethod:@"one" arguments:nil];    //弹出Flutter页面    [self presentViewController:self.flutterVc animated:YES completion:nil];    //监听Flutter页面的回调    [methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {        //如果是要退出        if([call.method isEqualToString:@"exit"]){            [self.flutterVc dismissViewControllerAnimated:YES completion:nil];        }    }];}- (IBAction)pushFlutterTwo:(id)sender {    //告诉Flutter显示one_page     FlutterMethodChannel * methodChannel = [FlutterMethodChannel methodChannelWithName:@"two_page" binaryMessenger:self.flutterVc];    [methodChannel invokeMethod:@"two" arguments:nil];     //弹出Flutter页面     [self presentViewController:self.flutterVc animated:YES completion:nil];     //监听Flutter页面的回调     [methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {         //如果是要退出         if([call.method isEqualToString:@"exit"]){             [self.flutterVc dismissViewControllerAnimated:YES completion:nil];         }     }];}- (void)viewDidLoad {    [super viewDidLoad];    self.flutterVc = [[FlutterViewController alloc] initWithEngine:self.flutterEngine nibName:nil bundle:nil];    self.msgChannel = [FlutterBasicMessageChannel  messageChannelWithName:@"messageChannel" binaryMessenger:self.flutterVc];    [self.msgChannel setMessageHandler:^(id  _Nullable message, FlutterReply  _Nonnull callback) {        NSLog(@"收到Flutter的%@",message);    }];}-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{    static int a = 0;    [self.msgChannel sendMessage:[NSString stringWithFormat:@"%d",a++]];}
 运行效果:复制代码void initState() {    _messageChannel.setMessageHandler((message) {      print('收到来自iOS的$message');      return Future(() {});    });    super.initState();    _oneChannel.setMethodCallHandler((call) {      pageIndex = call.method;      print(call.method);      setState(() {});      return Future(() {});    });    _twoChannel.setMethodCallHandler((call) {      pageIndex = call.method;      print(call.method);      setState(() {});      return Future(() {});    });  }  // This widget is the root of your application.  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'Flutter Demo',      theme: ThemeData(        primarySwatch: Colors.blue,      ),      home: _rootPage(pageIndex),    );  }  _rootPage(String pageIndex) {    switch (pageIndex) {      case 'one':        return Scaffold(          appBar: AppBar(            title: Text(pageIndex),          ),          body: Column(            mainAxisAlignment: MainAxisAlignment.center,            children: [              ElevatedButton(                onPressed: () {                  _oneChannel.invokeMapMethod('exit');                },                child: Text(pageIndex),              ),              TextField(                onChanged: (String str) {                  _messageChannel.send(str);                },              )            ],          ),        );      case 'two':        return Scaffold(          appBar: AppBar(            title: Text(pageIndex),          ),          body: Center(            child: ElevatedButton(              onPressed: () {                _twoChannel.invokeMapMethod('exit');              },              child: Text(pageIndex),            ),          ),        );      default:        return Scaffold(          appBar: AppBar(            title: const Text('default'),          ),          body: Center(            child: ElevatedButton(              onPressed: () {                _twoChannel.invokeMapMethod('exit');              },              child: Text(pageIndex),            ),          ),        );    }  }}
下面是理论先容:
 2.Flutter Channel
 
 Flutter 作为一个灵活的UI框架。无论是ios平台上的Objective-C或Swift,还是Android平台上的Java或Kotlin都可以通过Platform Channel 机制来与Flutter进行通讯。必要注意的是Platform Channel 不依赖代码生成,而是建立在消息通报方式上。实际上,它的工作模式和原理非常类似基于二进制协议开发的网络服务。
 iOS Channel 原理
 
 Flutter 提供了三种Channel用作Flutter与iOS原生平台之间的数据通报:
 1.FlutterBasicMessageChannel:用作字符串和半结构化的数据通报。
 
 2.FlutterMethodChannel:用来调用方法(method invocation),包括从 Flutter向原生平台发起方法调用,也支持从原生平台Flutter发起方法调用。复制代码**结构化数据:**: 包括预定义的数据类型、格式和结构的数据,常见的比如关系型数据库中数据表里的数据。**半结构化数据:**: 具有可识别的模式并可以解析的文本数据文件,比如XML数据文件。**非结构化数据:**: 没有固定结构的数据,通常保存为不同类型的文件,比如文本文档、图片、视频等。
3.FlutterEventChannel:用来支持数据流(streams)通信。
 三种 Channel 分别带来差别的作用。但是在筹划上大同小异。都有以下三个成员变量:
 
 用作消息的发送和接收的工具,重要负责Flutter与原生之间的相互通讯。
  name:Channel 名称 作为每一个Channel的唯一标记。在我们的Flutter 应用中,通常会存在多个 Platform Channel。 那么这些 Channel 之间就是通过唯一标记name 来区分。 例如,使用 FlutterMethodChannel发起方法调用时,就必要我们为MethodChannel指定对应name。
 
 messenger:消息信使(BinaryMessenger)
 普通来讲, messenger就是咱们现在的外卖小哥。messenger负责把数据从 Flutter 送到iOS平台,大概从iOS传输数据到Flutter。只管Flutter中存在三种差别用途的Channel, 但是对应的沟通工具都是 BinaryMessenger 。
 在创建一个 Channel 后,不论是通过设置署理 (Delegate),还是通过 setXXXHandler:来进行消息处理。终极会为该 Channel 绑定一个 FlutterBinaryMessageHandler。 并以 Channel的name作为key , 生存在一个 Map 结构中。 当接受到发送消息后,会根据消息中携带的 Channel 名称取出对应 FlutterBinaryMessageHandler, 并交由BinaryMessenger处理。
 注意:在 iOS平台BinaryMessenger 是一个名为 FlutterBinaryMessenger 的协议。
 3 .Codec (编解码器)
 
 在 Channel 中,messenger 携带的数据必要在 Dart 层, Native (iOS/Android平台)层中传输,所以就必要一种与平台无关的数据协议。既能支持图片,又能支持文件等资源。因此官方终极采用了二进制字节流作为数据传输协议。
 二进制字节流: 发送方法必要把数据编码成二进制数据,接收方再把数据解码成原始数据。而负责编解码操作的就是 Codec。
 在 Flutter 中有两种 Codec:
 MessageCodec:对message进行编解码 MessageCodec 用于二进制数据与底子数据之间的编解码,此中 FlutterBasicMessageChannel 中采用的就是该Codec。
 
 在 Flutter 中,MessageCodec有多种实现:复制代码//用于实现二进制数据NSData和不同类型数据之间的转换@protocol FlutterMessageCodec+(instancetype)sharedInstance;//将指定的类型message编码为二进制数据- (NSData *_nullable)encode:(id _nullable)message;//将二进制数据NSData解码成指定类型-(id _nullable)decode:(NSData* _nullabel)message;@end
 
 FlutterMethodCodec:对 FlutterMethodCall编解码
 FlutterStandardMessageCodec:是FlutterBasicMessageChannel 中默认使用的编解码器。(底层是用FlutterStandardReaderWriter 实现的)。用于数据类型和二进制数据之间的编解码。支持底子数据类型包(bool、char、double、float、int、long、short、String、Array、Dictionary)以及二进制数据。
FlutterBinaryCodec:用于二进制数据和二进制数据之间的编解码,在实现上只是原封不动的将接收到的二进制数据返回。
FlutterStringCodec:用于字符串与二进制数据之间的编解码,对于字符串采用 UTF-8编码格式。
FlutterJSONMessageCodec:用于数据类型与二进制数据之间的编解码,支持底子数据类型(bool、char、double、float、int、long、short、String、Array、Dictionary)。在iOS端使用 NSJSONSerialization作为序列化工具。
 FlutterMethodCodec 用于二进制数据与方法调用(FlutterMethodCall)和返回效果之间的编解码。重要用在FlutterMethodChannel 和 FlutterEventChannel中。
 
 复制代码@protocol FlutterMethodCodec+(instancetype)sharedInstance;//将FlutterMethodCall编码为二进制NSData-(NSData *)encodeMethodCall:(FlutterMethodCall*)methodCall;//将二进制NSData methodCall解码为FlutterMethodCall- (FlutterMethodCall *)decodeMethodCall:(NSData*)methodCall;//将正常响应结果result编码为二进制-(NSData*)encodeSuccess Envelope:(id _nullable)result;//将错误响应提示编码为二进制NSData-(NSData*)encodeErrorEnvelope:(FlutterError*)error;//将二进制数据NSData解码,失败返回FlutterError-(id _nullable)decodeEnvelope:(NSData*)envelope;
FlutterMethodCall 代表从 Flutter端发起的方法调用。方法调用包括:方法名、方法参数以及方法返回效果。因此和FlutterMessageCodec 相比,FlutterMethodCodec 中多了两个处理调用效果的方法:
 
 
 decodeEnvelope:方法则用与解码iOS平台代码调用Dart中方法的效果。好比通过FlutterMethodChannel调用Flutter中的方法,且得到其返回效果。
 方法调用成功:使用 encodeSuccessEnvelope:编码result。
方法调用失败:使用encodeErrorEnvelope:编码FlutterError。
 
 
 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
 |