Flutter 79: 圖解 Android Native 集成 FlutterBoost 小嚐試 (二)

      小菜前幾天剛嘗試接入 FlutterBoost,主要對其頁面路由的跳轉及傳參等有了初步的認識,接下來是對日常操作的基本學習;

      FlutterBoost 作爲 NativeFlutter 之間的橋接方式,兩端之間的數據傳遞是必不可少的;FlutterBoost 也是採用同樣 Platform Channel 進行橋接,最常用的就是 MethodChannel

插件註冊

      小菜在使用 Flutter Module 時會根據不同的業務模塊註冊不同的插件,小菜以前嘗試單純採用 Flutter 時需要 FlutterMain.startInitialization 初始化,而 FlutterBoost 也不例外;但是根據 FlutterBoost 的版本迭代,其註冊的方式也隨着有所變更,且必不可少;

      小菜嘗試的是 v1.12.13-hotfixes 版本,可以在 AndroidManifest.xml 中必須要添加 flutterEmbedding 版本設置註冊插件方式,同時也可以通過 GeneratedPluginRegistrant 手動方式註冊,此時均無需繼承 FlutterApplication

// AndroidManifest 方式註冊
<meta-data android:name="flutterEmbedding"
    android:value="2">
</meta-data>

// GeneratedPluginRegistrant 方式註冊
FlutterBoost.BoostPluginsRegister pluginsRegister = new FlutterBoost.BoostPluginsRegister() {
    @Override
    public void registerPlugins(PluginRegistry mRegistry) {
        GeneratedPluginRegistrant.registerWith(FlutterBoost.instance().engineProvider());
    }
};

創建通信通道 Platform Channel

      小菜在單純使用 Flutter 時,創建通信通道嘗試通過 MethodChannel / BasicMessageChannel / EventChannel,其中初始化時均需 FlutterView,小菜接入 FlutterBoost 後在 MainActivity 中創建通信通道,監聽 onMethodChannel,在 Flutter 端監聽到方法是可以正常通信的;

new MethodChannel(getFlutterView(), "test.ace.com/main").setMethodCallHandler(new MethodChannel.MethodCallHandler() {
    @Override
    public void onMethodCall(MethodCall call, MethodChannel.Result result) {
        if (call.method.equals("ace_demo_user")) {
            Toast.makeText(this, "當前 method 爲 ace_demo_user", Toast.LENGTH_LONG).show();
        } else {
            result.notImplemented();
        }
    }
});

      但是小菜是把 MainActivity 作爲 FlutterView 來處理的,這樣對於後期的維護以及業務方面的處理均不符合要求,並且據 FlutterBoost-issues 中提及在 v1.9 以後優化了創建通道的方法,在初始化 FlutterBoost 時會對 FlutterBoost LifeCycle 生命週期做監聽;可在 onPluginsRegistered() 方法中進行創建;這樣可以免去針對不同頁面的 FlutterView 設置;

FlutterBoost.BoostLifecycleListener boostLifecycleListener = new FlutterBoost.BoostLifecycleListener() {

    @Override
    public void onEngineCreated() {

    }

    @Override
    public void onPluginsRegistered() {
        BinaryMessenger messenger = FlutterBoost.instance().engineProvider().getDartExecutor();
        initMainMethod(messenger);
    }

    @Override
    public void onEngineDestroy() {

    }
};

private void initMainMethod(BinaryMessenger messenger) {
    MethodChannel mMainChannel = new MethodChannel(messenger, "test.ace.com/main");
    mMainChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
        @Override
        public void onMethodCall(MethodCall call, MethodChannel.Result result) {
            if (call.arguments != null) {
                Log.e("TAG", "回調內容:" + call.arguments.toString());
            }
            if (call.method != null) {
                Log.e("TAG", "回調方法:" + call.method.toString());
            }
            if (call.method.equals("ace_demo_user")) {
                result.success("");
            } else {
                result.notImplemented();
            }
        }
    });
}

監聽關閉路由

      在使用 FlutterBoost 時,小菜按照官網方式封裝了 openPageUrl 開啓路由的方法,對於特殊頁面的路由專場動畫也可以單獨設置,但對於關閉路由動畫卻不能直接設置;

      小菜分析源碼,在 Platform 中提供了 closeContainer() 方法,而其中 finishContainer() 可以通過獲取當前 Activity 來關閉路由;

// 源碼
public void closeContainer(IContainerRecord record, Map<String, Object> result, Map<String, Object> exts) {
    if (record == null) return;
    record.getContainer().finishContainer(result);
}

@Override
public void finishContainer(Map<String, Object> result) {
    if (result != null) {
        setBoostResult(this.host.getActivity(), new HashMap<>(result));
        this.host.getActivity().finish();
    } else {
        this.host.getActivity().finish();
    }
}

      closeContainer() 該方法並非抽象方法,但 Platform 是抽象類,所以小菜直接重寫 closeContainer() 即可;

Platform platform = new Platform() {
    @Override
    public Application getApplication() {
        return BaseApplication.getInstance();
    }

    @Override
    public void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode,
        Map<String, Object> exts) {
        router.openContainer(context, url, urlParams, requestCode, exts);
    }

    @Override
    public void closeContainer(IContainerRecord record, Map<String, Object> result, Map<String, Object> exts) {
        super.closeContainer(record, result, exts);
        // 獲取路由 Activity 設置轉場動畫
    }

    @Override
    public int whenEngineStart() {
        return FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED;
    }

    @Override
    public FlutterView.RenderMode renderMode() {
        return FlutterView.RenderMode.texture;
    }

    @Override
    public boolean isDebug() {
        return true;
    }

    @Override
    public String initialRoute() {
        return "/";
    }
};

小擴展

      小菜在一個歷史項目中集成 FlutterFlutterBoost 遇到 Cause: assert appProject != null 如下問題;

Cause: assert appProject != null
|          |
null       false

      小菜確定集成方式是正確的,於是查閱資料發現很容易解決;小菜歷史項目的主 Modulenews 更換爲 app 即可;這個問題並非大問題,希望有相同問題的朋友可以提前避免;


      小菜對 FlutterFlutterBoost 的研究還不夠深入,還在繼續學習探索,如有錯誤請多多指導!

來源: 阿策小和尚

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章