iOS与Flutter混合开发
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS与Flutter混合开发相关的知识,希望对你有一定的参考价值。
参考技术A 在现有ios项目中导入Flutter, 需要在Podfile文件中加入flutter_application_path = '/Users/../flutter_app_module'
load File.join(flutter_application_path,'.ios','Flutter','podhelper.rb')
并对target添加:
install_flutter_engine_pod
install_all_flutter_pods(flutter_application_path)
从上我们可以看到导入Flutter需要依赖Flutter项目中的'.ios'文件夹下的'podhelper.rb'文件,所以在pod install之前,请确认.ios文件夹存在
也许你一开始存在这个文件,但是在执行flutter clean之后,这个文件不见了,不用惊慌, .ios文件夹基本可以通过以下几种方式生成,自行选择:
1. flutter run
2. flutter pub get
3. flutter create .
.ios文件夹生成之后,回到原生项目pod install即可。
友情提示:
在生成.ios的时候,项目中不要存在其他的内层项目(如下截图),那可能会导致你无法生成.ios或者生成的.ios不包含podhelper.rb这个文件,而最终导致你pod install失败。
愉快的开始coding......
原生(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方案。
以上是关于iOS与Flutter混合开发的主要内容,如果未能解决你的问题,请参考以下文章
flutter 腾讯云 上传腾讯云cos 使用flutter1.12 1.17及以上版本 ios与flutter混合开发