需求
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(); } } }