ios原生嵌套Flutter模块

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ios原生嵌套Flutter模块相关的知识,希望对你有一定的参考价值。

参考技术A 通过以下命令解决

执行完毕后,Flutter module将会创建在ios项目/my_flutter目录下

将Flutter模块嵌入到现有iOS应用程序中有两种方式:

此方法需要所有的相关开发的人员安装 Flutter 环境。

需要在my_flutter文件夹下执行一下

把.ios和.android等flutter配置生成出来。

AppDelegate.h:

AppDelegate.m:

控制器:

flutter:

注册路由

通过全局FlutterEngine实例化FlutterViewController,并setInitialRoute设置初始化路由,这里发现设置的初始化路由路由并不管用

控制器:

设置FlutterViewController的pushRoute
这里其实只是让flutter方面push一次

新建一个FlutterViewController并把setInitialRoute设置为跳转的路由,不通过全局的FlutterEngine创建

放一个之前自己学习时写的demo,希望可以帮助新入门的老铁们,有好的建议可以提一下,我们一起进步,奥利给!!!
https://github.com/Baffin-HSL/Flutter_UI

原生(iOS)与Flutter混合开发步骤

一、前言:目前混合开发属于主流,因为多数都在原来的项目上集成Flutter模块,除非新的项目用纯Flutter,那是挺爽的。混合开发多数会有点坑吧。现在记录下混合开发的坑

二、集成(以iOS为例),使用Pods方式
1、首先创建一个Flutter模块(非Flutter项目,是模块)

2、创建后之后,把原生项目和Flutter模块放在一个文件夹下,同一层级。

3、原生项目打开Podfile,加入Flutter,如下

// my_flutter 是创建Flutter的模块名称
flutter_application_path = '../my_flutter'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

platform :ios, '9.0' 
target 'NativeIOS' do
  use_frameworks!
  /// 这边引入
  install_all_flutter_pods(flutter_application_path)
  /// 其他
  ...
end

4、在原生目录下,pod install,在pod install之前,先在Flutter模块下执行 flutter pub get
4.1、 Flutter模块下 执行 flutter pub get
4.2、 在原生项目下 执行 pod install
如果以上不报错,混合开发模式到这里就集成完了。,可以好好的玩耍了。不过好像想的有点多…

5、Flutter模块那边怎么写还是怎么写,Flutter模块也是可以跑起来的。

6、在原生项目中注册Flutter引擎, 就是flutterEngine。 在启动的时候就注册,这样后续就不会出现卡顿的样式,有点儿难受。

/// 在AppDelegate入口初始化即可
#pragma mark - initFlutterEngine
- (void)initFlutterEngine {
    self.flutterEngine = [[FlutterEngine alloc] initWithName:@"WMFlutterEngine"];
    [self.flutterEngine run];
    [GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine];
}

/// 修改如下改成 FlutterEngine
@interface AppDelegate : FlutterEngine 

7、在原先项目需要跳转的地方写业务即可了。

/// 某个原生控制器
// testPushFlutterPage 跳转的地方 ,其中self.flutterVC 是我单独的一个类 见8 
/// 跳转到Flutter页面。
- (void)testPushFlutterPage {
    self.flutterVC.fd_prefersNavigationBarHidden = YES;
    [self showViewController:self.flutterVC sender:nil];
}

- (void)initMethodChannel {
    self.flutterVC = [[WMFlutterViewController alloc] init];
    [self.flutterVC initMethodChannel];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initMethodChannel];
}

8、flutterVC类

#pragma mark - Initial Methods // 初始化的方法
- (instancetype)init
{
    self = [super init];
    if (self) {
       self = [[WMFlutterViewController alloc] initWithEngine:[self getFlutterEngine] nibName:nil bundle:nil];
    }
    return self;
}

//
- (void)initMethodChannel {
    FlutterMethodChannel *methodChannel = [FlutterMethodChannel methodChannelWithName:@"PatientSearchChannel" binaryMessenger:self.binaryMessenger];
    self.methodChannel = methodChannel;
    //通过block回调监听通道中来自flutter的消息体 这里做一个dismiss方法,由于iOS中将flutter页面push出来,次数实现dismiss方法,给flutter发送dismss消息,就知道是让iOS将当前页面关闭的动作,iOS收到后,执行关闭操作
    __weak typeof(self) weakself = self;
    [methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
        __strong typeof(weakself) strongself = weakself;
        //dissmiss当前页面
        if([call.method isEqualToString:@"dismiss"]){
//            [strongself.flutterVC dismissViewControllerAnimated:YES completion:nil];
            [strongself.navigationController popViewControllerAnimated:YES];
        }
        if (result) {
            result(@"回到的地方");
        }
        
        //dissmiss当前页面
        if([call.method isEqualToString:@"pushNative"]){
            WMLog(@"pushNative 进来了 数据是 %@", call.arguments);
            WMNoticeSetViewController *VC = [[WMNoticeSetViewController alloc] init];
            WMLog(@"%@", self .navigationController);
            [self.navigationController pushViewController:VC animated:YES];
        }
        
        //dissmiss当前页面
        if([call.method isEqualToString:@"pushNativeTwo"]){
            WMLog(@"pushNativeTwo 进来了 数据是 %@", call.arguments);
            NSDictionary *dataDic = call.arguments;
            WMTestViewController *VC = [[WMTestViewController alloc] init];
            VC.name = dataDic[@"name"];
            WMLog(@"%@", self.navigationController);
            [self.navigationController pushViewController:VC animated:YES];
        }
    }];
}

/// 获取引擎
- (FlutterEngine *)getFlutterEngine {
    FlutterEngine *flutterEngine = ((AppDelegate *)UIApplication.sharedApplication.delegate).flutterEngine;
    return flutterEngine;
}

以后原生部分就写完了。

9、Flutter部分,我写了一个工具类,来和原生交互的类

class NativeChannelUtils {
  static const MethodChannel _patientSearchChannel =
      MethodChannel('PatientSearchChannel');

  /// 患者搜索关闭
  static patientSearchDismiss({WMValueCallBack valueCallBack}) {
    _patientSearchChannel.invokeMethod("dismiss").then((value) {
      Utils.logs('回来的数据 = ${value}');
      if (valueCallBack != null) {
        valueCallBack(value);
      }
    });
  }

  /// 患者搜索到原生界面
  static patientSearchPushToNative({WMValueCallBack valueCallBack}) {
    _patientSearchChannel.invokeMethod(
        "pushNative", {"data": "我是Flutter数据", 'code': '1000'}).then((value) {
      Utils.logs('回来的数据 = ${value}');
      if (valueCallBack != null) {
        valueCallBack(value);
      }
    });
  }

  /// 患者搜索到原生界面
  static patientSearchPushToNativeTwo(
      {Map arguments, WMValueCallBack valueCallBack}) {
    _patientSearchChannel
        .invokeMethod("pushNativeTwo", arguments)
        .then((value) {
      Utils.logs('回来的数据 = ${value}');
      if (valueCallBack != null) {
        valueCallBack(value);
      }
    });
  }
}

在Flutter需要的地方调用。

NativeChannelUtils.patientSearchDismiss(valueCallBack: (value) {
            Utils.logs("哈哈哈哈");
          });

`
注意点:原生和Flutter交互有三种方式,目前使用的MethodChannel方式

MethodChannel:Flutter 与 Native 端相互调用,调用后可以返回结果,可以 Native 端主动调用,也可以Flutter主动调用,属于双向通信。此方式为最常用的方式, Native 端调用需要在主线程中执行。
BasicMessageChannel:用于使用指定的编解码器对消息进行编码和解码,属于双向通信,可以 Native 端主动调用,也可以Flutter主动调用。
EventChannel:用于数据流(event streams)的通信, Native 端主动发送数据给

这个是Flutter原生方式混合开发。由于是在项目中集成的,后期看下 提出demo.

这边我用闲鱼的flutter_boost 混合开发方案 写了一个demo。
demo地址:https://github.com/yj229201093/NavateFlutterDemo

但总觉得和自己想要的差一点点东西。所以目前采用原生方式混合开发。

注意:如果使用原生方式,尽量不要开多个引擎,不然开销很大,就是:下面就开启了两个引擎。Flutter引擎是相互独立的。互不干扰的。
原生A->FlutterB,
FlutterB->FlutterC,
FlutterC->原生D,
原生D->FlutterE

建议是一个闭环开发,一个项目开启一个Flutter引擎。就是原生进入Flutter模块,然后Flutter模块结束后就回到原生,这样算一个闭环。

如果反复跳转可以使用闲鱼的flutter_boost方案。

后续可能采用flutter_boost方案。目前导航栏方便还有点没有理清。

以上是关于ios原生嵌套Flutter模块的主要内容,如果未能解决你的问题,请参考以下文章

原生(iOS)与Flutter混合开发步骤

原生(iOS)与Flutter混合开发步骤

原生(iOS)与Flutter混合开发步骤

原生(iOS)与Flutter混合开发步骤

flutter与原生混编(iOS)

ios flutter 混编