Flutter 混合開發實戰問題記錄(一)FlutterView閃爍

小豬睡枕頭single發表於2019-02-27

本人主要從事android開發,從開始研究到專案實戰接入大概有一個半月了,前期的摸索階段花的時間不是很多,每天抽出1小時來看,學習路線大概是:

搭建環境---語言熟悉---寫demo---寫案例----摘取實際專案中的模組完全翻譯為dart版本----接入到專案中
複製程式碼

目前還算順利,遇到的問題大都解決了。dart語法類似於js,也和java8,kt等以後的語法糖相通,熟悉下即可上手。

我隨手記錄了些比較繁瑣難解決,實施不是很簡單的問題,類似於widget佈局等就不再詳細描述了,只是時間問題,熟悉下就行了。

我們專案中嵌入Flutter的入口是主頁的第四個tab,需要一個fragment,可以在flutterfragment中return flutterView。

public class MyFlutterFragment extends BaseFlutterFragment implements BasicMessageChannel.MessageHandler<String>{
    private BasicMessageChannel<String> messageChannel;
    @Override
    public FlutterView onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        FlutterView flutterView = Flutter.createView(
                mActivity,
                getLifecycle(),
                "routename");
        messageChannel = new BasicMessageChannel<>(flutterView, "android_channel", StringCodec.INSTANCE);
        messageChannel.setMessageHandler(this);
        //todo 註冊你的methodChannel
        // ......
        return flutterView;
    }

    @Override
    public void onMessage(String s, BasicMessageChannel.Reply<String> reply) {
       //todo
    }
}

複製程式碼

向你的flutter的main()方法中傳遞routename 然後啟動相應的widget,本身沒有什麼問題,嵌入之後widget渲染和請求也ok,只是在切換flutterFragment和nativeFragment的時候出現了明顯的閃爍,而nativeFragment之間切換則沒有。

翻閱原始碼可以看到flutterView本身就是surfaceView,做android原生開發朋友知道,即使不使用flutter,在做自定義相機,視訊渲染,以及類似於XWalkView 的使用中都會遇到類似問題。

對flutter瞭解不深,不明白為何選取surface來做載體,使用textureView會有什麼問題。

【Surfaceview的特性】:內部維護了兩個執行緒即主執行緒和渲染執行緒,渲染執行緒可以在主執行緒之外的執行緒中向螢幕上繪圖。這樣可以避免主執行緒因繪圖任務繁重導致程式的阻塞,從而提高了程式的反應速度。在遊戲開發中多用surfaceView,遊戲的背景,任務,動作儘量在畫布Canvas中繪製。這種雙執行緒的設計模式,極大的消耗了CPU記憶體,為此,SurfaceView可見時才被建立,SurfaceView隱藏時便被銷燬,從而達到節約記憶體的目的。 
複製程式碼

搜尋資料,由於場景不同解決方案也不同。

1 假如單頁面中巢狀surfaceView,可以在Activity的onCreate()方法中加上一句話:

getWindow().setFormat(PixelFormat.TRANSLUCENT);
複製程式碼

或在rootview中構建一個長寬為0px 並且不可見的SurfaceView。

2 有人遇到了xwalkView中的閃爍,https://blog.csdn.net/qq2364121253/article/details/82253996,解決方案在文章內。

3 有人在flutter的GitHub issue中提了問題,主要是在原生中啟動flutter頁面(而非act中嵌入Fragment)的閃爍和黑屏問題,和重置flutterView大小遇到的問題

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

綜合幾種方案,可以找到一個比較簡單的方式, 構建你的flutterView後設定屬性

public class MyFlutterFragment extends BaseFlutterFragment implements BasicMessageChannel.MessageHandler<String>{
   private BasicMessageChannel<String> messageChannel;
   @Override
   public FlutterView onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       FlutterView flutterView = Flutter.createView(
               mActivity,
               getLifecycle(),
               "routename");
       
       //新增        
       flutterView.setZOrderOnTop(true);
       flutterView.getHolder().setFormat(PixelFormat.TRANSLUCENT);  
       
       messageChannel = new BasicMessageChannel<>(flutterView, "android_channel", StringCodec.INSTANCE);
       messageChannel.setMessageHandler(this);
       //todo 註冊你的methodChannel
       // ......
       return flutterView;
   }

   @Override
   public void onMessage(String s, BasicMessageChannel.Reply<String> reply) {
      //todo
   }
}
複製程式碼

後續我會繼續做記錄,標記一些問題,最近在弄混合棧,在原生-flutter - web中自由跳轉,借鑑鹹魚的混合棧(因為有些bug和不必要功能,暫時沒有采用)的思路,大家都可以寫出自己的路由棧。

相關文章