flutter 混合开发踩坑日记

  1. flutter与原生交互主要需要处理两个问题

①路由跳转

  • 使用咸鱼的FlutterBoost(目前项目正在使用中...) 下载demo,移植部分代码即可使用
  • 使用哈喽出行提供的解决方案flutter_thrio,据说内存处理上比咸鱼要做的好,还没有验证,目前更新频率很高,待日后稳定后可以试着用一下
  • 使用消息通道MethodChannel,建立消息体系,通过发送消息的方式来跳转页面,这样做就需要自己去管理flutter引擎,需要让flutter引擎全局持有,这样才能每次打开页面的时候只在同一个引擎环境下操作,防止重复创建引擎造成的内存问题

②消息通道

  • BasicMessageChannel通用数据传输,全双工,实时传递
  • MethodChannel方法传递通道,传递只执行一次 全双工
  • EventChannel事件监听通道持续监听如果电池电量的监听
    这里只写MethodChannel写几个方法实现flutter与iOS的方法互调
    在iOS中首先要创建消息通道并初始化通道名,这样后面所有消息都通过这个通道名对应的通道传递
//初始化通道
FlutterMethodChannel *methodChannel = [FlutterMethodChannel methodChannelWithName:@"MSGChannel" binaryMessenger:self.flutterViewController.binaryMessenger];
self.methodChannel = methodChannel;

//通过block回调监听通道中来自flutter的消息体 这里做一个dismiss方法,由于iOS中将flutter页面push出来,次数实现dismiss方法,给flutter发送dismss消息,就知道是让iOS将当前页面关闭的动作,iOS收到后,执行关闭操作
__weak typeof(self) weakself = self;
[methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
    __strong typeof(weakself) strongself = weakself;
    //dissmiss当前页面
    if([call.method isEqualToString:@"dismiss"]){
        [strongself dismissViewControllerAnimated:YES completion:nil];
    }
    if (result) {
        result(@"成功关闭页面");
    }
}];

//iOS中也可以主动给Flutter发消息通过invokeMethod 只需要注意消息通道名要跟初始化保持一致
[self.methodChannel invokeMethod:@"MSGChannel" arguments:@"我是iOS发送过来的消息"];
  1. 关于如何在现有项目中搭建混合开发环境,请参考往期文章 flutter 与iOS混合开发
  2. 通过咸鱼搭建的路由体系 MethodChannel需要在Flutter_boost初始化完毕后再初始化
   //初始化flutter路由
    PlatformRouterImp *router = [PlatformRouterImp new];
    [FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router
                                                        onStart:^(FlutterEngine *engine) {
        //初始化消息通道
        [[MSGChannelManager shareManager] setBinaryMessenger:engine.binaryMessenger];
        //设置代理
        [MSGChannelManager shareManager].delegate = self;
        //发送消息测试
        [[MSGChannelManager shareManager] sendEvent:@"push" arguments:@{@"abc":@"dcb"} result:nil];
    }];
    self.router = router;

MSGChannelManager在iOS环境下创建消息管理类,通过MSGChannelManager来创建消息通道,并全局持有
注意:binaryMessenger:从咸鱼初始化完成后拿到并在消息通道初始化的时候用到,Android也一样,否则,创建的消息通道无法实现互通

   /// 收消息 并通道代理全局多转发
   [methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
        if([call.method isEqualToString:MSG_METHOD_NAME]){
            NSDictionary *params = call.arguments;
            NSString *name = params[@"name"];
            NSDictionary *arguments = params[@"arguments"];
            //消息转发
            for (id delegate in self.delegateHash) {
                if (delegate && [delegate respondsToSelector:@selector(msgChannel:name:arguments:)]) {
                    [delegate msgChannel:weakself.methodChannel name:name arguments:arguments];
                    
                }            }
        }else{
           result(FlutterMethodNotImplemented);
        }
    }];

    /// 发消息 通过MehodName
-(void)sendEvent:(NSString *)eventName
       arguments:(NSDictionary *)arguments
          result:(FlutterResult _Nullable)callback{
    if(!eventName) return;
    NSMutableDictionary *msg = [NSMutableDictionary new];
    msg[@"name"] = eventName;
    msg[@"arguments"] = arguments;
    [self.methodChannel invokeMethod:MSG_METHOD_NAME
                           arguments:msg
                              result:callback];
}
  1. 通过Flutter_boost在iOS环境中,可以将Flutter页面放在Tabbar上,就比如咸鱼的个人中心模块,全部都是使用的flutter完成,这样也会相对带来一些坑
    ①项目中TabBar中有两个模块使用Flutter来完成,在使用过程中,由于在flutter中加入了webView,所以在info.plist中加入了io.flutter.embedded_views_preview=true 导致在两个flutter页面来回切换过程中闪屏严重,移除该字段后,能解决问题
    ②由后台切换到前台,导致原生页面莫名卡住,初步诊断认为可能是切换到后台后,系统会释放掉部分flutter引擎的一部分内存消耗,从而导致页面卡住不动,解决方法,让app进入后台后,仍然可以长期持有并保存,可以开启一个后台服务Background Modes,后台远程推送,或者后台播放音乐,让app保持活性
    ③将flutter页面作为二级页面,不放在Tabbar上,能够解决上面所有问题[😓]

  2. 页面布局使用自定义StatefulWidget组件,发现页面值不更新的情况,通过设置UniqueKey()能够解决页面setsate不刷新的问题,原理请参考往期文章flutter StatefulWidget组件不刷新

  3. flutter module模式下 pubspec.yaml最下面的androidPackage、iosBundleIdentifier保持默认就好,也不要跟原生项目保持一致,否则,生成的.android和.ios会和原生项目bundleId一样,这样,Android在打包时会出现包名重复等一些未知问题,所以请别手贱[dog],这两个参数是用来给生成的.android .ios生成默认包名和bundleId的

  module:
    androidX: true
    androidPackage: com.example.flutter_xxxx
    iosBundleIdentifier: com.example.flutter_xxxx
  1. 整个开发过程中发现iOS的问题比较多,Android的问题偏少,安卓需要处理好路由跳转问题,和页面销毁问题,iOS则会有页面闪屏,闪退,内存过爆,页面卡主等一系列问题

  2. flutter在页面布局确实有他的优势,效率超级高,但是也有一些flutter自己的一些问题,如webView的处理问题,textField的输入问题,输入框不居中需要设置contentPading的问题,混合开发中初始化FlutterContoller会重复创建引擎问题,但是,后面随着flutter的更新迭代,我想这些问题也都会慢慢解决,但是带来的优势却是相当大的,开发周期缩短,人员成本减少等,后期还是无限看好flutter

posted @ 2020-05-30 10:15  qqcc1388  阅读(1941)  评论(2编辑  收藏  举报