需求
flutter需要調(diào)用多個Flutter界面,且需要傳輸數(shù)據(jù)到flutter
問題
由于最開始的與iOS的混編,是只調(diào)用一個界面,而現(xiàn)在需要調(diào)用多個。所以這里我們是通過FlutterEngine初始化FlutterViewController,并通過設(shè)置setInitialRoute設(shè)置初始化路由,以下是交互的代碼
<!--OC代碼-->
//通過engine創(chuàng)建flutter界面
FlutterEngine flutterEngine = [[FlutterEngine alloc] initWithName:@"flutter engine"];
[flutterEngine run];
FlutterViewController *flutterVC = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
//設(shè)置路由
[flutterVC setInitialRoute:@"message"];
//消息傳遞通道,native傳遞到flutter
FlutterMethodChannel *flutterChannel = [FlutterMethodChannel methodChannelWithName:@"nativeToFluuter" binaryMessenger:flutterVC.binaryMessenger];
[flutterChannel invokeMethod:@"message" arguments:@{@"message":@"hello world"}];
[self.navigationController pushViewController:flutterVC animated:YES];
<!--Flutter代碼-->
void main() => runApp(_widgetForRoute(ui.window.defaultRouteName));
Widget _widgetForRoute(String route){
switch (route){
case 'message':
return MyApp();
case 'other':
return OtherPage();
default:
return DefaultPage();
}
}
但是通過實測發(fā)現(xiàn),setInitialRoute設(shè)置的路由并不生效,在flutter端通過 window.defaultRouteName拿到的route永遠是/根符號。這個是Flutter SDK的一個bug
解決辦法有以下幾種
方式1 -
如果必須使用setInitialRoute來區(qū)分不同的flutter界面,那么就不能通過FlutterEngine初始化FlutterViewController,需要直接使用 alloc+init 或者 new 的方式初始化FlutterViewController。
注:這種方式有一個問題,每次渲染會有
啟動頁一閃而過的效果,且這種方式初始化的FlutterViewController在關(guān)閉時是無法釋放內(nèi)存的
改進后的代碼如下所示
<!--OC代碼-->
//通過alloc+init創(chuàng)建flutter界面
FlutterViewController *flutterVC = [[FlutterViewController alloc] init];
//設(shè)置路由
[flutterVC setInitialRoute:@"message"];
//消息傳遞通道,native傳遞到flutter
FlutterMethodChannel *flutterChannel = [FlutterMethodChannel methodChannelWithName:@"nativeToFluuter" binaryMessenger:flutterVC.binaryMessenger];
[flutterChannel invokeMethod:@"message" arguments:@{@"message":@"hello world"}];
[self.navigationController pushViewController:flutterVC animated:YES];
<!--Flutter代碼-->
void main() => runApp(_widgetForRoute(ui.window.defaultRouteName));
Widget _widgetForRoute(String route){
switch (route){
case 'message':
return MyApp();
case 'other':
return OtherPage();
default:
return DefaultPage();
}
}
方式2
通過FlutterMethodChannel傳入的method進行區(qū)分,以下是代碼邏輯
<!--OC代碼-->
//通過alloc+init創(chuàng)建flutter界面
FlutterViewController *flutterVC = [[FlutterViewController alloc] init];
//消息傳遞通道,native傳遞到flutter
FlutterMethodChannel *flutterChannel = [FlutterMethodChannel methodChannelWithName:@"nativeToFluuter" binaryMessenger:flutterVC.binaryMessenger];
[flutterChannel invokeMethod:@"message" arguments:@{@"message":@"hello world"}];
[self.navigationController pushViewController:flutterVC animated:YES];
<!--Flutter代碼-->
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
//用于區(qū)分不同界面
String pageRoute;
dynamic arguments;
@override
void initState() {
super.initState();
ConstantsUtil.nativeToFlutterChannel.setMethodCallHandler((call) {
setState(() {
pageRoute = call.method;
arguments = call.arguments;
});
return null;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: rootPage(pageRoute),
);
}
rootPage(String route){
switch (route){
case 'message':
return MessagePage(title: 'Message', arguments: arguments,);
case 'other':
return OtherPage(title: 'Other', arguments: arguments,);
default:
return DefaultPage();
}
}
}