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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM