iOS开发Flutter探索-与原生混合开发(11)

前言

混合开发(Hybird模式)是当下大部分APP开发的主流方式。通常我们将APP内变化比较频繁,业务比较轻,且对性能要求不是特别高的的功能,通过一些非原生的手段来实现,比如最简单的嵌套一个WebView,然后通过JSBridge的方式来实现双向通行,从而实现页面的动态更新;同样的在React Native,Weex,和Flutter中都提供的混合开发的能力。今天我们就看下Flutter如何与原生混合开发(这里主要以iOS开发为例);
这里需要注意的是如果需要支持混合开发,整个Flutter项目需要创建为Module,然后将Module引入iOS/Android项目中,iOS通过cocoaPods来引入并加载。

创建Flutter-Module项目

截屏2020-06-22下午10.19.06.png
项目结构对比

两种类型项目对比.png

我发现的唯一区别就是原来的androidios文件夹变成了隐藏文件。而且Module项目是可以独立运行的。

创建一个iOS项目

通常在Flutter混合开发项目中,我们的iOS或者Android项目会创建在Module的同级目录下(实际上就是为了引用个时候方便,其实我们完全可以将Module创建在任意位置,只是在项目中引用时路径太恶心罢了)。

  • 通过pod引入引入flutter_module,配置Podfile:
# Uncomment the next line to define a global platform for your project
flutter_application_path = '../flutter_module'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

platform :ios, '9.0'

use_frameworks!
target 'Flutter_iOS' do
  install_all_flutter_pods(flutter_application_path)
end

执行pod install,此时我们的原生项目就引入了整个flutter_module

  • 原生调起Flutter模块
#import "ViewController.h"
#import 
@interface ViewController ()
@property (nonatomic,strong) FlutterViewController *flutterVC;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.flutterVC = [[FlutterViewController alloc]init];
}
- (IBAction)toFlutterModule:(UIButton *)sender {  
    [self presentViewController:self.flutterVC animated:YES completion:nil];
}
@end

这里值得注意的是flutterVC的初始化我没有放在点击事件内部,而是放在viewDidLoad中,FlutterViewController是一个特殊的视图控制器,并不像我们平常使用的UIViewController,在dismiss或者pop后会被释放,它不会被释放而且它被创建后的生命周期跟AppDelegate是一致的。
在纯flutter项目中,FlutterViewController通常被指定为UIApplication.keyWindow.rootViewController

调起效果图.gif

通信

这里主要用到的是MethodChannel

Flutter官方图

MethodChannel中两个核心的方法:

  1. setMethodCallHandler: 注册监听,处理收到的消息
  2. invokeMethod: 发送消息
  • Flutter
class _HomePageState extends State {
  //创建通道,设置通道标识
  final MethodChannel _msgChannel = MethodChannel('msg_channel');
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    //添加监听,接受来自native的消息
    _msgChannel.setMethodCallHandler((MethodCall call){
      print('收到iOS的消息=>${call.method}\n${call.arguments}');
      return null;
    });
  }
GestureDetector(
    onTap: (){
        print('onTap.....');
        //向native发送消息
        _msgChannel.invokeMethod('disMissVC',{'name':'zezefamily','age':'3','from':'Shannxi of China'});
    },
    child:  Text('返回上一页'),
)
  • Native
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.flutterVC = [[FlutterViewController alloc]init];
    //创建通道,并绑定通道标识
    self.methodChannel = [FlutterMethodChannel methodChannelWithName:@"msg_channel" binaryMessenger:self.flutterVC];
    //添加监听:接收来自Flutter的消息
    __weak typeof(self) weakSelf = self;
    [self.methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
        
        if([call.method isEqualToString:@"disMissVC"]){
            [weakSelf dismissVC:call.arguments];
        }
        
    }];
}
- (void)dismissVC:(id)arguments
{
    NSLog(@"来自Flutter=>%@",arguments);
    [self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)nativeToFlutter:(UIButton *)sender {
    //Native=>Flutter
    [self.methodChannel invokeMethod:@"msg_channel" arguments:@{@"name":@"我是原生",@"desc":@"我给你发消息了"}];
}

控制台输出:

2020-06-23 15:20:54.568666+0800 Flutter_iOS[64555:1302095] flutter: onTap.....
2020-06-23 15:20:54.569892+0800 Flutter_iOS[64555:1301842] 来自Flutter=>{
    age = 3;
    from = "Shannxi of China";
    name = zezefamily;
}
2020-06-23 15:20:56.594187+0800 Flutter_iOS[64555:1302095] flutter: 收到iOS的消息=>msg_channel
{name: 我是原生, desc: 我给你发消息了}

这样就实现了一个双向的通信能力,非常类似于WebViewJavascriptBridge

j4i8b-w6dwn.gif

总结

参考文献:https://flutter.dev/docs/development/add-to-app

你可能感兴趣的:(iOS开发Flutter探索-与原生混合开发(11))