本篇采用Flutter_boost实现分别从原生和Flutter两个维度的代码层面,来介绍内容它们之间的交互方案,
主要有以下步骤:
1.Flutter如何集成Flutter_boost框架
2.iOS如何引入boost的代码实现
3.iOS如何与flutter实现交互
一、Flutter如何集成Flutter_boost框架
1.首先,需要添加FlutterBoost依赖到yaml文件
flutter_boost:
git:
url: 'https://github.com/alibaba/flutter_boost.git'
ref: '4.2.0'
之后在flutter工程下运行flutter pub get
2.在main.dart文件引入boost,并代码实现集成
import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
void main() {
///这里的CustomFlutterBinding调用务必不可缺少,用于控制Boost状态的resume和pause
CustomFlutterBinding();
runApp(const MyApp());
}
///创建一个自定义的Binding,继承和with的关系如下,里面什么都不用写
class CustomFlutterBinding extends WidgetsFlutterBinding with BoostFlutterBinding {}
3.接入路由跳转
Map<String, FlutterBoostRouteFactory> routerMap = {
'indexPage': (settings, uniqueId) {
return PageRouteBuilder<dynamic>(
settings: settings,
pageBuilder: (_, __, ___) => const IndexPager());
},
'loginPage': (settings, uniqueId) {
return PageRouteBuilder<dynamic>(
settings: settings,
pageBuilder: (_, __, ___) => LoginPager());
},
'withParamPage': (settings, uniqueId) {
return PageRouteBuilder<dynamic>(
settings: settings,
pageBuilder: (_, __, ___) => WithParamPage(uniqueId, settings.arguments as Map<String, dynamic>));
},
};
到此dart端就集成完毕了
二、iOS引入Flutter_boost框架
1.首先到自己的iOS目录下,执行pod init,之后执行一次pod install
2.打开创建的Podfile文件,添加以下代码
flutter_application_path = '../gtech-flutter-sdk'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
install_all_flutter_pods(flutter_application_path)
添加之后,Podfile应该类似下面这样
flutter_application_path = '../gtech-flutter-sdk'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'flutter_swift' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
install_all_flutter_pods(flutter_application_path)
end
post_install do |installer|
flutter_post_install(installer) if defined? (flutter_post_install)
end
然后再执行pod install,安装完成
3.进行准备工作创建FlutterBoostDelegate
import flutter_boost
class BoostDelegate: NSObject,FlutterBoostDelegate {
static let shared = BoostDelegate()
///您用来push的导航栏
var navigationController:UINavigationController?
///用来存返回flutter侧返回结果的表
var resultTable:Dictionary<String,([AnyHashable:Any]?)->Void> = [:];
func pushNativeRoute(_ pageName: String!, arguments: [AnyHashable : Any]!) {
print(arguments)
//可以用参数来控制是push还是pop
let isPresent = arguments["isPresent"] as? Bool ?? false
let isAnimated = arguments["isAnimated"] as? Bool ?? true
//这里根据pageName来判断生成哪个vc,这里给个默认的了
var targetViewController = UIViewController()
if(pageName == "native_main"){
let demo = DemoViewController()
demo.title = "原生测试页"
let data = arguments?["data"]
let phone = arguments?["mobile"]
let value1 = data!
let value2 = phone!
targetViewController = demo
self.navigationController?.popViewController(animated: true)
demo .setdata(data: value1 as! String, mobile: value2 as! String)
}
if(isPresent){
BoostDelegate.shared.navigationController?.present(targetViewController, animated: isAnimated, completion: nil)
}else{
BoostDelegate.shared.navigationController?.pushViewController(targetViewController, animated: isAnimated)
}
}
func pushFlutterRoute(_ options: FlutterBoostRouteOptions!) {
let vc:FBFlutterViewContainer = FBFlutterViewContainer()
vc.setName(options.pageName, uniqueId: options.uniqueId, params: options.arguments,opaque: options.opaque)
//用参数来控制是push还是pop
let isPresent = (options.arguments?["isPresent"] as? Bool) ?? false
let isAnimated = (options.arguments?["isAnimated"] as? Bool) ?? true
//对这个页面设置结果
resultTable[options.pageName] = options.onPageFinished;
//如果是present模式 ,或者要不透明模式,那么就需要以present模式打开页面
if(isPresent || !options.opaque){
self.navigationController?.present(vc, animated: isAnimated, completion: nil)
}else{
self.navigationController?.pushViewController(vc, animated: isAnimated)
}
}
func popRoute(_ options: FlutterBoostRouteOptions!) {
//如果当前被present的vc是container,那么就执行dismiss逻辑
if let vc = self.navigationController?.presentedViewController as? FBFlutterViewContainer,vc.uniqueIDString() == options.uniqueId{
//这里分为两种情况,由于UIModalPresentationOverFullScreen下,生命周期显示会有问题
//所以需要手动调用的场景,从而使下面底部的vc调用viewAppear相关逻辑
if vc.modalPresentationStyle == .overFullScreen {
//这里手动beginAppearanceTransition触发页面生命周期
self.navigationController?.topViewController?.beginAppearanceTransition(true, animated: false)
vc.dismiss(animated: true) {
self.navigationController?.topViewController?.endAppearanceTransition()
}
}**else**{
//正常场景,直接dismiss
vc.dismiss(animated: **true**, completion: **nil**)
}
}else{
self.navigationController?.popViewController(animated: true)
}
//否则直接执行pop逻辑
//这里在pop的时候将参数带出,并且从结果表中移除
if let onPageFinshed = resultTable[options.pageName] {
onPageFinshed(options.arguments)
resultTable.removeValue(forKey: options.pageName)
}
}
}
4.在AppDelegate的didFinishLaunchingWithOptions方法中进行初始化
//创建代理,做初始化操作
let delegate = BoostDelegate()
FlutterBoost.instance().setup(application, delegate: delegate) { engine in
}
到此为止,所有的前置内容均已完成
三、iOS如何与Flutter交互
1.头部引用flutter_boost
import flutter_boost
2.原生通过路由跳转到Flutter指定页面
原生代码:
//跳转到首页
@objc func clickHome(btn:UIButton) {
let options = FlutterBoostRouteOptions()
options.pageName = "indexPage"
BoostDelegate.shared.pushFlutterRoute(options)
}
Flutter代码:
'indexPage': (settings, uniqueId) {
return PageRouteBuilder<dynamic>(
settings: settings,
pageBuilder: (_, __, ___) => const IndexPager());
},
3.通过原生通过路由传参数给Flutter
原生代码:
//跳转到个人中心
@objc func clickMine() {
let options = FlutterBoostRouteOptions()
options.pageName = "withParamPage"
options.arguments = ["string": "床前明月光,疑是地上霜","bool":"true","int":"2023"]
options.uniqueId = "李白"
options.completion = { completion **in**
print("open operation is completed")
}
BoostDelegate.shared.pushFlutterRoute(options)
}
Flutter代码:
'withParamPage': (settings, uniqueId) {
return PageRouteBuilder<dynamic>(
settings: settings,
pageBuilder: (_, __, ___) => WithParamPage(uniqueId, settings.arguments as Map<String, dynamic>));
},
4.Flutter打开原生路由
原生代码:
if(pageName == "native_main"){
let demo = DemoViewController()
demo.title = "原生测试页"
targetViewController = demo
self.navigationController?.popViewController(animated: true)
}
Flutter代码:
BoostNavigator.instance.push("native_main", arguments: {'data': "我是flutter传过来的参数",'mobile': "15821963583"});
5.接受来自Flutter的事件&数据
原生代码:
//这里注册事件监听,监听flutter发送到iOS的事件
self.backListener = FlutterBoost.instance().addEventListener({[weak self] key, dic in
//在这里处理你的事件
print(dic ?? "")
print("接受到来自 flutter的事件 ");
let back = dic?["com"] as! String
lbl1.text = "flutter 返回 " + back
self?.navigationController?.popViewController(animated: true)
}, forName: "eventToNative")
Flutter代码:
BoostChannel.instance.sendEventToNative("eventToNative",{"android":"mmj","com":"shanghai"});
四、各版本包大小对比
iOS空包:31k
Flutter集成boost包:7.6M
iOS集成Flutter后的包: 7.7M