美文网首页
Flutter学习资源汇总持续更新中....

Flutter学习资源汇总持续更新中....

作者: 陈科比大宝贝儿 | 来源:发表于2024-06-12 14:28 被阅读0次

    常用三方类库

    
    flutter_lints                   - Flutter团队推荐的Flutter相关规则集
    
    cupertino_icons                 -  加载苹果风格的图标
    
    ios_platform_images             -  share images between Flutter and iOS
    
    flutter_boost                   -  新一代Flutter-Native混合解决方案
    
    flustars                        -  Flutter常用工具类库,包括日期、时间、正则、log日志、json转换、屏幕相关
    
    shared_preferences              -  本地数据存取插件 ,在Android上它是基于 SharePreferences的,在iOS上它是基于 NSUserDefaults
    
    

    flutter_boost

    随着Flutter的发展,国内越来越多的App开始使用Flutter。为了降低风险,大部分App采用渐进式方式引入Flutter,在App里选几个页面用Flutter来编写,但都碰到了相同的问题,在原生页面和Flutter页面共存的情况下,如何管理路由? 官方没有提供这样的解决方案,而FlutterBoost就是为了解决这个问题而生。

    FlutterBoost的使命是让开发者非常简单的在原生App中开发Flutter页面。

    很多Flutter开发者只会一端,只会Android 或者只会IOS,但他需要接入双端,所以双端统一能降低他的 学习成本和接入成本。FlutterBoost3.0,在设计上 Android和IOS都做了对齐,特别接口上做到了参数级的对齐。

    新一代Flutter-Native混合解决方案。 FlutterBoost是一个Flutter插件,它可以轻松地为现有原生应用程序提供Flutter混合集成方案。FlutterBoost的理念是将Flutter像Webview那样来使用。在现有应用程序中同时管理Native页面和Flutter页面并非易事。 FlutterBoost帮你处理页面的映射和跳转,你只需关心页面的名字和参数即可(通常可以是URL)。

    将FlutterBoost添加到你的Flutter工程依赖中

    
    flutter_boost:
        git:
            url: 'https://github.com/alibaba/flutter_boost.git'
            ref: 'v3.0-release.2'
    
    

    之后在flutter工程下运行flutter pub get dart端就集成完毕了

    将FlutterBoost集成到Android部分和iOS部分

    将FlutterBoost添加到你的iOS工程依赖中

    首先到自己的iOS目录下,执行一次pod install

    
    yushuhuideMacBook-Pro:wargame_cloudgame_ios yushuhui$ pod install
    Analyzing dependencies
    Downloading dependencies
    Installing FlutterPluginRegistrant 0.0.1
    Installing flutter_boost (0.0.2)
    Installing ios_platform_images (0.0.1)
    Installing path_provider_ios (0.0.1)
    Installing shared_preferences_ios (0.0.1)
    Generating Pods project
    Integrating client project
    Pod installation complete! There are 31 dependencies from the Podfile and 45 total pods installed.
    
    
    

    进行准备工作创建FlutterBoostDelegate。 这里面的内容是完全可以自定义的,在您了解各个API的含义时,你可以完全自定义这里面每个方法的代码,下面只是给出大多数场景的默认解法

    
    import flutter_boost
    
    class BoostDelegate: NSObject,FlutterBoostDelegate {
        
        static let shared = BoostDelegate()
        
        ///您用来push的导航栏
        var navigationController:UINavigationController?
        
        var flutterVC:FBFlutterViewContainer?
        
        ///用来存返回flutter侧返回结果的表
        var resultTable:Dictionary<String,([AnyHashable:Any]?)->Void> = [:];
        
        func pushNativeRoute(_ pageName: String!, arguments: [AnyHashable : Any]!) {
            
            //可以用参数来控制是push还是pop
            let isPresent = arguments["isPresent"] as? Bool ?? false
            let isAnimated = arguments["isAnimated"] as? Bool ?? true
            //这里根据pageName来判断生成哪个vc,这里给个默认的了
            var targetViewController = UIViewController()
            
            if(isPresent){
                self.navigationController?.present(targetViewController, animated: isAnimated, completion: nil)
            }else{
                self.navigationController?.pushViewController(targetViewController, animated: isAnimated)
            }
        }
        
        func pushFlutterRoute(_ options: FlutterBoostRouteOptions!) {
            let vc:FBFlutterViewContainer = FBFlutterViewContainer()
            vc.setName(options.pageName, uniqueId: options.uniqueId, params: options.arguments,opaque: options.opaque)
            self.flutterVC = vc
            
            //用参数来控制是push还是pop
            let isPresent = (options.arguments?["isPresent"] as? Bool)  ?? false
            let isAnimated = (options.arguments?["isAnimated"] as? Bool) ?? true
            
            //对这个页面设置结果
            resultTable[options.pageName] = options.onPageFinished;
            
            //如果是present模式 ,或者要不透明模式,那么就需要以present模式打开页面
            if(isPresent || !options.opaque){
                self.navigationController?.present(vc, animated: isAnimated, completion: nil)
            }else{
                self.navigationController?.pushViewController(vc, animated: isAnimated)
            }
        }
        
        func popRoute(_ options: FlutterBoostRouteOptions!) {
            //如果当前被present的vc是container,那么就执行dismiss逻辑
            if let vc = self.navigationController?.presentedViewController as? FBFlutterViewContainer,vc.uniqueIDString() == options.uniqueId{
                
                //这里分为两种情况,由于UIModalPresentationOverFullScreen下,生命周期显示会有问题
                //所以需要手动调用的场景,从而使下面底部的vc调用viewAppear相关逻辑
                if vc.modalPresentationStyle == .overFullScreen {
                    
                    //这里手动beginAppearanceTransition触发页面生命周期
                    self.navigationController?.topViewController?.beginAppearanceTransition(true, animated: false)
                    
                    vc.dismiss(animated: true) {
                        self.navigationController?.topViewController?.endAppearanceTransition()
                    }
                }else{
                    //正常场景,直接dismiss
                    vc.dismiss(animated: true, completion: nil)
                }
            }else{
                self.navigationController?.popViewController(animated: true)
            }
            //否则直接执行pop逻辑
            //这里在pop的时候将参数带出,并且从结果表中移除
            if let onPageFinshed = resultTable[options.pageName] {
                onPageFinshed(options.arguments)
                resultTable.removeValue(forKey: options.pageName)
            }
        }
    }
    
    

    在AppDelegate的didFinishLaunchingWithOptions方法中进行初始化

    
    //创建代理,做初始化操作
    import flutter_boost
    let flutterBoostDelegate = BoostDelegate()
    
    FlutterBoost.instance().setup(application, delegate: flutterBoostDelegate, callback: { engine in
                
    })
    
    

    iOS原生跳转到flutter模块的settingPage页面

    
    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            let flutterBtn = UIButton()
            flutterBtn.backgroundColor = ColorConst.color_e8f4
            flutterBtn.layer.cornerRadius = 5
            flutterBtn.layer.masksToBounds = true
            flutterBtn.setTitle("toFlutterVC", for: .normal)
            flutterBtn.setTitleColor(ColorConst.color_28, for: .normal)
            flutterBtn.addTarget(self, action: #selector(clickToSettingVC), for: .touchUpInside)
            flutterBtn.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
            view.addSubview(flutterBtn)
        }
    
        @objc func clickToSettingVC() {
            // 创建options,进行open操作的构建
            let options = FlutterBoostRouteOptions()
            options.pageName = "settingPage"
            options.arguments = ["data": "settingPage", "isPresent": false, "isAnimated": true]
    
            // 这个是push操作完成的回调,而不是页面关闭的回调!!!!
            options.completion = { _ in
                print("open operation is completed")
            }
    
            // 这个是页面关闭并且返回数据的回调,回调实际需要根据您的Delegate中的popRoute来调用
            options.onPageFinished = { [weak self] dic in
                if let data = dic?["data"] as? String {
                    print("settingPage return data is: \(data)")
                }
            }
            BoostDelegate.shared.navigationController = UIViewController.current.navigationController
            BoostDelegate.shared.pushFlutterRoute(options)
        }
    }
    
    
    

    flutter run 配置iOS证书

    
    vim ~/.flutter_settings
    
    
    {
      "ios-signing-cert": "Apple Development: XXXX@gmail.com (XXXXXXXX)",
      "enable-macos-desktop": true
    }
    
    

    单独调试某个flutter页面示例,无需经过集成到原生工程

    
    Widget appBuilder(Widget home) {
        return const MaterialApp(
          home: MySettingPage(), // 这里是需要调试的页面的名称
          // home: home,
          debugShowCheckedModeBanner: false,
    
          ///必须加上builder参数,否则showDialog等会出问题
          // builder: (_, __) {
          //   return home;
          // },
        );
    
    

    将FlutterBoost添加到你的android工程依赖中,原生和flutter通信的各种情况如下:

    1. Android 原生携带参数打开flutter页面

           HashMap<String, Object> map = new HashMap<>();//传递给flutter的参数map
           map.put("data","1");
           map.put("UserName","2");
           map.put("HeaderUrl","3");
           map.put("CurrUserId","4");
           FlutterBoostRouteOptions options = new FlutterBoostRouteOptions.Builder()
                   .pageName("settingPage") //settingPage打开的flutter页面的名称
                   .arguments(map)
                   .requestCode(1111)
                   .build();
           FlutterBoost.instance().open(options);
      

      flutter接收传递的数据:

      Map<String, FlutterBoostRouteFactory> routerMap = {
       'settingPage': (settings, uniqueId) {
         return CupertinoPageRoute(
             settings: settings,
             builder: (_) {
      
               Map<String, Object> map = settings.arguments as Map<String, Object>;
               print("收到原生传递的消息:"+ map.toString());
               String data = map['data'] as String;
               print("收到原生传递的消息 data:"+ data.toString());
               return MySettingPage(
                 data: data,
               );
             });
       },  };
      
      
      
    2. flutter携带参数打开Android原生页面

       var user = {
        'data' : 'number',
        'age': 'turtledoves'
      }; 
      MainActivity:打开Android原生的目标页面。user传递的参数
    

    Android原生接收:
    先发送消息到原生,原生收到消息后,进行分发打开原生界面:

     EventListener listener = (key, args) -> {
             Log.d("EventListener", "onCreate: args ----key是:" + key+ "--------args是: "+ args);
             if (key.equals("event")){
    //                Map<Object, Object> args
                     if (args.get("data").equals("Logout")){
                         startActivity(new Intent(this, MainActivity.class));
                     }
                 }
             }
         };
         remover = FlutterBoost.instance().addEventListener("event", listener);
    
    1. flutter向Android原生发送消息

      发送的key是data,value是一个map集合
      BoostChannel.instance.sendEventToNative("event", {'data': "UserInfo"});
      

      Android原生接收消息:
      EventListener listener = (key, args) -> {

           Log.d("EventListener", "onCreate: args ----key是:" + key+ "--------args是: "+ args);
       };
      

      ListenerRemover remover = FlutterBoost.instance().addEventListener("event", listener);

      注意://最后在清理的时候移除监听(比如onDestroy中) remover.remove();

    2. Android向Flutter发送消息

      Map<Object,Object> map = new HashMap<>();
      map.put("key","value");
      FlutterBoost.instance().sendEventToFlutter("eventToFlutter",map);
      

      flutter端接收:

    ```
    ///声明一个用来存回调的对象
    VoidCallback removeListener;
    
    ///添加事件响应者,监听native发往flutter端的事件
    removeListener = BoostChannel.instance.addEventListener("yourEventKey", (key, arguments) {
      ///deal with your event here
      return;
    });
    
    ///然后在退出的时候(比如dispose中)移除监听者
    removeListener?.call();
    ```
    

    相关文章

      网友评论

          本文标题:Flutter学习资源汇总持续更新中....

          本文链接:https://www.haomeiwen.com/subject/xgxnqjtx.html