概要

前一篇文章中我们提到,iOS跳转到Flutter工程指定页面时(多个),Flutter只有单例,设置setInitialRouter 无效,如下

  1. let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!
  2. flutterViewController.setInitialRoute("test1")

基于不是很甘心,一直想实现完美的解决方案,所以最近几天又看了下解决各方面的解决方案,最终还是有了可行方案,步骤如下

1、设置delegate 代码

这里代码 多了 ‘FlutterBasicMessageChannel’  设置,其中_kReloadChannelName要和 flutter上的代码保持一致

  1. let _kReloadChannelName = "reload"
  2.  
  3. @UIApplicationMain
  4. class AppDelegate: UIResponder, UIApplicationDelegate ,FlutterAppLifeCycleProvider{
  5.  
  6. static var shared: AppDelegate?
  7.  
  8. var window: UIWindow?
  9.  
  10. var _lifeCycleDelegate = FlutterPluginAppLifeCycleDelegate()
  11. var flutterEngine : FlutterEngine!
  12. var flutterViewController : RKFlutterViewController!
  13. var reloadMessageChannel : FlutterBasicMessageChannel!
  14.  
  15. func addApplicationLifeCycleDelegate(_ delegate: FlutterPlugin) {
  16. _lifeCycleDelegate.add(delegate)
  17. }
  18.  
  19. func flutterSetup(){
  20. flutterEngine = FlutterEngine(name: "rokid.flutter", project: nil)
  21. flutterEngine.run(withEntrypoint: nil)
  22. //全局引擎(解决启动加载时候m,无法处理和native交互问题)
  23. flutterViewController = RKFlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!
  24. GeneratedPluginRegistrant.register(with: flutterEngine)
  25. //实现App 路由跳转
  26. reloadMessageChannel = FlutterBasicMessageChannel(name: _kReloadChannelName, binaryMessenger: flutterEngine, codec: FlutterStringCodec.sharedInstance())
  27. }
  28.  
  29. func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  30. ...
  31. flutterSetup()
  32. ...
  33. }

2、iOS App 跳转指定路由

  1. @objc func handleButtonAction() {
  2. self.engine().navigationChannel.invokeMethod("setInitialRoute", arguments: "test")
  3. self.reloadMessageChannel().sendMessage("test")
  4. let flutterViewController = FlutterViewController(engine: self.engine(), nibName: nil, bundle: nil)!
  5. self.navigationController?.pushViewController(flutterViewController, animated: true)
  6. }
  7.  
  8. func engine() -> FlutterEngine {
  9. return (UIApplication.shared.delegate! as! AppDelegate).flutterEngine
  10. }
  11.  
  12. func reloadMessageChannel() -> FlutterBasicMessageChannel {
  13. return (UIApplication.shared.delegate! as! AppDelegate).reloadMessageChannel
  14. }

3、flutter路由代码如下

  1. import 'package:flutter/material.dart';
  2. import 'package:flutter/services.dart';
  3. import 'dart:ui' as ui;
  4. import 'src/pages/playground/PlaygroundPage.dart';
  5.  
  6. /// Channel used to let the Flutter app know to reset the app to a specific
  7. /// route. See the [run] method.
  8. ///
  9. /// Note that we shouldn't use the `setInitialRoute` method on the system
  10. /// navigation channel, as that never gets propagated back to Flutter after the
  11. /// initial call.
  12. const String _kReloadChannelName = 'reload';
  13. const BasicMessageChannel<String> _kReloadChannel =
  14. BasicMessageChannel<String>(_kReloadChannelName, StringCodec());
  15.  
  16. void main(){
  17. // Start listening immediately for messages from the iOS side. ObjC calls
  18. // will be made to let us know when we should be changing the app state.
  19. _kReloadChannel.setMessageHandler(run);
  20. // Start off with whatever the initial route is supposed to be.
  21. run(ui.window.defaultRouteName);
  22. }
  23.  
  24. Future<String> run(String name) async{
  25. // The platform-specific component will call [setInitialRoute] on the Flutter
  26. // view (or view controller for iOS) to set [ui.window.defaultRouteName].
  27. // We then dispatch based on the route names to show different Flutter
  28. // widgets.
  29. // Since we don't really care about Flutter-side navigation in this app, we're
  30. // not using a regular routes map.
  31. switch (name) {
  32. case "test":
  33. runApp(appRouter(title: "我是路由测试test00",));
  34. break;
  35. case "test1":
  36. runApp(appRouter(title: "我是路由测试test01",));
  37. break;
  38. case "test2":
  39. runApp(appRouter(title: "我是路由测试test02",));
  40. break;
  41. default:
  42. runApp(MyApp());
  43. break;
  44. }
  45. return '';
  46. }
  47.  
  48. class appRouter extends StatelessWidget {
  49. appRouter({this.title});
  50.  
  51. final String title;
  52. // This widget is the root of your application.
  53. @override
  54. Widget build(BuildContext context) {
  55. return MaterialApp(
  56. title: 'Flutter rokid',
  57. debugShowCheckedModeBanner: false,// 显示和隐藏
  58. theme: ThemeData(
  59. primarySwatch: Colors.blue,
  60. ),
  61. home: PlaygroundPage(title: '$title'),
  62. );
  63. }
  64. }
  65.  
  66. class MyApp extends StatelessWidget {
  67. // This widget is the root of your application.
  68. @override
  69. Widget build(BuildContext context) {
  70. return MaterialApp(
  71. title: 'Flutter rokid',
  72. debugShowCheckedModeBanner: false,// 显示和隐藏
  73. theme: ThemeData(
  74. // This is the theme of your application.
  75. //
  76. // Try running your application with "flutter run". You'll see the
  77. // application has a blue toolbar. Then, without quitting the app, try
  78. // changing the primarySwatch below to Colors.green and then invoke
  79. // "hot reload" (press "r" in the console where you ran "flutter run",
  80. // or press Run > Flutter Hot Reload in a Flutter IDE). Notice that the
  81. // counter didn't reset back to zero; the application is not restarted.
  82. primarySwatch: Colors.blue,
  83. ),
  84. home: PlaygroundPage(title: '若琪实验室'),
  85. routes: <String ,WidgetBuilder>{
  86. "router1": (_) => new PlaygroundPage(title: "我是内部路由测试test00",),
  87. "router2": (_) => new PlaygroundPage(title: "我是内部路由测试test01",)
  88. },
  89. );
  90. }
  91. }

思考和总结

上面代码可以实现:native -> 任意 flutter   ,但是flutter Engine是单例子,能否实现 native->flutter ->native->flutter呢?

功能和交互如何去选择呢???

参考资料

https://github.com/flutter/flutter/issues/27882

https://github.com/flutter/flutter/blob/master/dev/integration_tests/ios_add2app/ios_add2app/MainViewController.m

https://github.com/flutter/flutter/blob/master/dev/integration_tests/ios_add2app/flutterapp/lib/main.dart

iOS 工程实现native 跳转指定的Flutter 页面的更多相关文章

  1. silverlight 跳转指定的aspx页面

    1.在xaml.cs中直接访问.并传递参数 System.Windows.Browser.HtmlPage.Window.Navigate(new Uri(HtmlPage.Document.Docu ...

  2. Flutter-现有iOS工程引入Flutter

    前言 Flutter 是一个很有潜力的框架,但是目前使用Flutter的APP并不算很多,相关资料并不丰富,介绍现有工程引入Flutter的相关文章也比较少.项目从零开始,引入Flutter操作比较简 ...

  3. react native 之 在现有的iOS工程中集成react native

    在现有的iOS工程中集成react native, 或者说将react native引入到iOS 项目,是RN和iOS混合开发的必经之路 参考官网教程:https://reactnative.cn/d ...

  4. iOS实现在webview页面内点击链接,跳转指定App

    早上和UI刚谈到这个需求,然后自己试了一下,发现还是蛮简单的,记录一下: 思路分析: iOS内应用之间跳转都会用到 URL Schemes这个东西,简单的讲,这个就是用来定义app身份的一个id识别, ...

  5. iOS 工程自动化 - 思路整理

    4 月份参加 2017@Swift 大会的时候有幸听到了 @zesming 大佬关于美团组件化的 Topic,有一张图印象特别深刻. 来自 @zesming 大佬 后来跟 @zesming 大佬沟通怎 ...

  6. Mac中搭建 iOS 的 React Native 环境

    手把手教你在Mac中搭建iOS的 React Native环境 http://www.cnblogs.com/damnbird/p/6074607.html 准备工作 1.你需要一台Mac电脑..(这 ...

  7. iOS 工程自动化 - OCLint

    前言 最近一直在做 iOS 工程自动化方向的事情,所以把自己研究和实践的内容进行记录并分享,希望能给大家一些帮助. 为什么要使用 OCLint 做为一个静态代码分析工具,我们引入 OCLint 的目的 ...

  8. iOS界面之间的跳转方式

    iOS界面之间的跳转方式基本有3种. .改变window的根视图 [self.window setRootViewController:VC]; .模态弹出 [self presentViewCont ...

  9. Android通过JNI实现守护进程与卸载后跳转指定网页

    JNI进程守护 c代码部分如下:JNIEXPORT void JNICALL Java_com_sharetimes_qude_jni_JNIDaemon_daemon(JNIEnv * env, j ...

随机推荐

  1. Nginx学习——location和rewrite

    location语法: location [=|~|~*|^~] /uri/ { … } 记住以下即可: 完全匹配(=) 无正则普通匹配(^~)(^ 表示“非”,~ 表示“正则”,字符意思是:不要继续 ...

  2. scala 列表List

    列表: 列表是不可变,也就是说不能通过赋值改变列表的元素: 列表有递归结构,而数据是连续的 List 类型:List() 同样也是List(String) 列表是基于Nil (是空的)和::(列表从前 ...

  3. 入门 Webpack,看这篇就够

    写在前面的话 阅读本文之前,先看下面这个webpack的配置文件,如果每一项你都懂,那本文能带给你的收获也许就比较有限,你可以快速浏览或直接跳过:如果你和十天前的我一样,对很多选项存在着疑惑,那花一段 ...

  4. java-day24

    JDBC控制事务: 1.事务:一个包含多个步骤的业务操作,如果这个业务操作被事务管理,则这个步骤要么同时成功,要么同时失败. 2. 操作:         1. 开启事务         2. 提交事 ...

  5. 高程(三)----数组Array

      一.数组的创建 var arrayObj = new Array(); //创建一个数组 var arrayObj = new Array([size]); //创建一个数组并指定长度,注意不是上 ...

  6. python 中 random模块的用法

    import random print( random.randint(1,10) ) # 产生 1 到 10 的一个整数型随机数 print( random.random() ) # 产生 0 到 ...

  7. Ansible-随笔-7

    扩展Ansible的插件系统. 有的时候,如果Ansible内置的插件无法满足需求时,我们可以自己编写新插件. 以下情况下可以考虑开发新插件: 1.除Paramiko.本机SSH.Local.Winr ...

  8. 从身份证号提取生日并更新到生日字段中的SQL语句

    1:根据身份证号 更新 生日字段 SQL update 学生信息 ,)+,)+,) 2:根据身份证号 更新 性别字段 SQL update 学生信息 set 性别='男' and substring( ...

  9. linux redis安装及JAVA使用jedis

    一.redis安装 1.安装redis 将redis安装包放到指定目录下.并用tar -zxvf redis.*****.tar.gz解压2.想把redis安装到哪里,就在哪里创建redis文件夹. ...

  10. [转]Netty入门(最简单的Netty客户端/服务器程序)

    Java中的NIO是一种解决阻塞式IO问题的基本技术,但是NIO的编写对java程序员是有比较高的要求的.那么Netty就是一种简化操作的一个成熟的网络IO编程框架.这里简单介绍一个程序,代码是< ...