背景
具有一定混合方案的App通常有一套通用的基础库,一般需要依赖很多基础库。使用flutter重新开发App的成本和风险都比较高。在Native App进行渐进式迁移是比较稳健的方式,所以就有了使用咸鱼flutter_boost混合解决方案。
准备工作
创建flutter_module
在使用flutter_boost之前,首先要生成flutter_module
包。如果你是使用最新版的Andrider Studio
新建工程直接选择flutter_module
就可以创建成功,除此之外也可以使用终端命令创建:
- 新建文件夹
flutter_boost_test
- 终端创建
flutter_module
,cd
到刚才创建的文件夹
cd /Users/mac/Desktop/flutter_boost_test
执行命令flutter create -t module flutter_module
创建iOS 工程
1:使用Xcode
创建iOS
工程,工程名为iOSflutter
,集成cocoaPods
,工程位置放在刚才创建的flutter_boost_test
文件夹里面,它与flutter_module
是同一级别的。
2:将flutter_module
与iOSflutter
关联,打开iOS
工程中Podfile
文件,填写如下代码:
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
# 配置
flutter_application_path = '../flutter_module/'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'iOSflutter' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for iOSflutter
# 配置
install_all_flutter_pods(flutter_application_path)
end
终端cd
到iOS
工程,执行pod install
命令,如下所示即成功:
集成flutter_boost
使用工具打开flutter_module
找到pubspec.yaml
添加依赖
dependencies:
flutter_boost: ^1.17.1
点击查看flutter_boost具体依赖版本和介绍,get package
之后,再次打开终端cd
到iOS
工程,执行pod install
命令,如图所示即成功:
flutter_boost 使用
iOS端
首先创建 router
类,这个可以直接按照咸鱼的demo
来写
#import
#import
NS_ASSUME_NONNULL_BEGIN
//@protocol FLBPlatform;
/**
* 实现平台侧的页面打开和关闭,不建议直接使用用于页面打开,建议使用FlutterBoostPlugin中的open和close方法来打开或关闭页面;
* FlutterBoostPlugin带有页面返回数据的能力
*/
@interface PlatformRouterImp : NSObject
@property (nonatomic,strong) UINavigationController *navigationController;
@end
NS_ASSUME_NONNULL_END
#import "PlatformRouterImp.h"
#import "UIViewControllerDemo.h"
@implementation PlatformRouterImp
- (void)openNativeVC:(NSString *)name urlParams:(NSDictionary *)params exts:(NSDictionary *)exts{
UIViewControllerDemo *vc = [[UIViewControllerDemo alloc] initWithNibName:@"UIViewControllerDemo" bundle:[NSBundle mainBundle]];
BOOL animated = [exts[@"animated"] boolValue];
if ([params[@"present"] boolValue]) {
[self.navigationController presentViewController:vc animated:animated completion:^{
}];
}else{
[self.navigationController pushViewController:vc animated:animated];
}
}
#pragma mark - boost 1.5
/**
可以根据 url 进行 页面跳转
*/
- (void)open:(NSString *)url urlParams:(NSDictionary *)urlParams exts:(NSDictionary *)exts completion:(void (^)(BOOL))completion{
NSLog(@"flutter跳转native的url %@",url);
if ([url isEqualToString:@"native"]) {
[self openNativeVC:url urlParams:urlParams exts:exts];
NSLog(@"platformRouterImp");
return;
}
BOOL animated = [exts[@"animated"] boolValue];
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:url params:urlParams];
[urlParams enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"key:%@",key);
NSLog(@"obj:%@",obj);
}];
[self.navigationController pushViewController:vc animated:animated];
if (completion) {
completion(YES);
}
}
- (void)present:(NSString *)url urlParams:(NSDictionary *)urlParams exts:(NSDictionary *)exts completion:(void (^)(BOOL))completion {
BOOL animated = [exts[@"animated"] boolValue];
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:url params:urlParams];
[self.navigationController presentViewController:vc animated:animated completion:^{
if(completion) completion(YES);
}];
}
- (void)close:(NSString *)uid result:(NSDictionary *)result exts:(NSDictionary *)exts completion:(void (^)(BOOL))completion {
BOOL animated = [exts[@"animated"] boolValue];
animated = YES;
FLBFlutterViewContainer *vc = (id)self.navigationController.presentedViewController;
if([vc isKindOfClass:FLBFlutterViewContainer.class] && [vc.uniqueIDString isEqual: uid]){
[vc dismissViewControllerAnimated:animated completion:^{}];
}else{
[self.navigationController popViewControllerAnimated:animated];
}
}
@end
AppDelegate
的里面的代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
PlatformRouterImp *router = [PlatformRouterImp new];
[FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router onStart:^(FlutterEngine * _Nonnull engine) {
}];
return YES;
}
在原生页面可以使用一下代码进行跳转
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.navigationItem.title = @"我是原生类 UIViewControllerDemo";
}
- (IBAction)pushFlutterPage:(id)sender {
[FlutterBoostPlugin open:@"first" urlParams:@{kPageCallBackId:@"MycallbackId#1"} exts:@{@"animated":@(YES)} onPageFinished:^(NSDictionary *result) {
NSLog(@"call me when page finished, and your result is:%@", result);
} completion:^(BOOL f) {
NSLog(@"page is opened");
}];
}
- (IBAction)present:(id)sender {
[FlutterBoostPlugin open:@"second" urlParams:@{@"present":@(YES),kPageCallBackId:@"MycallbackId#2"} exts:@{@"animated":@(YES)} onPageFinished:^(NSDictionary *result) {
NSLog(@"call me when page finished, and your result is:%@", result);
} completion:^(BOOL f) {
NSLog(@"page is presented");
}];
}
flutter
端:
首先在main.dart
进行跳转注册代码如下:
class _MyHomePageState extends State {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
void initState() {
// TODO: implement initState
super.initState();
FlutterBoost.singleton.registerPageBuilders({
'embeded': (String pageName, Map params, String _) =>
EmbeddedFirstRouteWidget(),
'first': (String pageName, Map params, String _) => FirstRouteWidget(),
'firstFirst': (String pageName, Map params, String _) =>
FirstFirstRouteWidget(),
'second': (String pageName, Map params, String _) => SecondRouteWidget(),
'secondStateful': (String pageName, Map params, String _) =>
SecondStatefulRouteWidget(),
'tab': (String pageName, Map params, String _) => TabRouteWidget(),
'platformView': (String pageName, Map params, String _) =>
PlatformRouteWidget(),
'flutterFragment': (String pageName, Map params, String _) =>
FragmentRouteWidget(params),
///可以在native层通过 getContainerParams 来传递参数
'flutterPage': (String pageName, Map params, String _) {
print('flutterPage params:$params');
return FlutterRouteWidget(params: params);
},
});
FlutterBoost.singleton.addBoostNavigatorObserver(TestBoostNavigatorObserver());
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: 'Flutter boost example',
builder: FlutterBoost.init(postPush: _onRoutePushed),
home: Container(color: Colors.white,),
);
}
void _onRoutePushed(String pageName,String uniqueId,Map params,Route route,Future_){}
}