Flutter筆記 02:iOS調(diào)用多個flutter界面

需求

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();
    }
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容