需求
flutter需要调用多个Flutter界面,且需要传输数据到flutter
问题
由于最开始的与iOS的混编,是只调用一个界面,而现在需要调用多个。所以这里我们是通过FlutterEngine
初始化FlutterViewController
,并通过设置setInitialRoute
设置初始化路由,以下是交互的代码
<!--OC代码-->
//通过engine创建flutter界面
FlutterEngine flutterEngine = [[FlutterEngine alloc] initWithName:@"flutter engine"];
[flutterEngine run];
FlutterViewController *flutterVC = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
//设置路由
[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();
}
}
但是通过实测发现,setInitialRoute
设置的路由并不生效
,在flutter端通过 window.defaultRouteName
拿到的route永远是/
根符号。这个是Flutter SDK的一个bug
解决办法有以下几种
方式1 -
如果必须使用setInitialRoute
来区分不同的flutter界面,那么就不能通过FlutterEngine初始化FlutterViewController,需要直接使用 alloc+init
或者 new
的方式初始化FlutterViewController
。
注:这种方式有一个问题,每次渲染会有
启动页一闪而过
的效果,且这种方式初始化的FlutterViewController在关闭时是无法释放内存
的
改进后的代码如下所示
<!--OC代码-->
//通过alloc+init创建flutter界面
FlutterViewController *flutterVC = [[FlutterViewController alloc] init];
//设置路由
[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
进行区分,以下是代码逻辑
<!--OC代码-->
//通过alloc+init创建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> {
//用于区分不同界面
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();
}
}
}