flutter Native 通信之FlutterBridge

為什么會(huì)開發(fā)這個(gè)框架

在flutter和Native混合開發(fā)的過程中我們難免會(huì)遇到flutter和Native相互通信的場景,這時(shí)我們就會(huì)用到flutter提供的 Flutter Platform Channel能力。大部分情況我們使用的都是 MethodChannel,一般我們會(huì)這樣是用。

flutter中使用methodchannel
  //聲明 methodchannel
  static const MethodChannel LUXURY_METHOD_CHANNEL = MethodChannel('flutter_native_channel');


    //注冊(cè)方法監(jiān)聽
    MethodChannelHolder.LUXURY_METHOD_CHANNEL.setMethodCallHandler((MethodCall methodCall) async {
     switch (methodCall.method) {
      case "methodA": 
        ......;
        break;
      case "methodB": 
        ......;
        break;
    }
    });
    
    //調(diào)用 方法
 var result = await MethodChannelHolder.LUXURY_METHOD_CHANNEL.invokeMethod(MethodHolder.COMMON_GOTO_HOME, {"isAll": path.isNotEmpty? "0": isAll});
原生中使用
    //聲明 methodchannel
    val LUXURY_METHOD_CHANNEL = MethodChannel(dartExecutor,"flutter_native_channel")
    
    //注冊(cè)方法監(jiān)聽
    MethodChannelHolder.LUXURY_METHOD_CHANNEL.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result ->
            when {
                "methodA" -> {
                   .....
                }
                "methodB" -> {
                    .....
                }
                else -> {
                    result.notImplemented()
                }
            }
        }
        
    //調(diào)用 方法
    MethodChannelHolder.LUXURY_METHOD_CHANNEL.invokeMethod("nativeCall/bbb", hashMapOf("cc" to "dd"),object :MethodChannel.Result{
                override fun notImplemented() {
                    LogUtil.e("原生 調(diào)用 flutter 收到 回調(diào) notImplemented")
                }

                override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) {
                    LogUtil.e("原生 調(diào)用 flutter 收到 回調(diào) error = $errorMessage")
                }

                override fun success(result: Any?) {
                    LogUtil.e("原生 調(diào)用 flutter 收到 回調(diào) success result=${result}")
                }

            })

那么我們直接使用MethodChannel會(huì)有哪些不方便或者問題呢?

  1. 使用前必須要手動(dòng)聲明一個(gè)MethodChannel,這也太麻煩了。(手動(dòng)狗頭)
  2. 方法注冊(cè)的位置被限定死,必須要在 MethodCallHandler的 onMethodCall 中聲明,而且沒有辦法反注冊(cè)。
  3. Native端的調(diào)用和回調(diào)必須保證在主線程。

基于這些問題于是就有了flutter_bridge.

如何封裝

1. 解決“必須要手動(dòng)聲明一個(gè)MethodChannel問題”

我們會(huì)在框架初始化的時(shí)候會(huì)自動(dòng)創(chuàng)建一個(gè)MethodChannel,這樣我們就不用自己創(chuàng)建MethodChannel了,也不用想channel的命名了,哈哈哈

//flutter
class FlutterBridge {
  static const String CHANNEL_NAME = "flutterBridge/core";
  MethodChannel _channel = new MethodChannel(CHANNEL_NAME);

  FlutterBridge._() {
    _channel.setMethodCallHandler(onMethodCall);
  }
}

//native
fun initChannel(messenger: BinaryMessenger) {
    channel = MethodChannel(messenger, CHANNEL_NAME)
    channel.setMethodCallHandler(this)
}

2. 解決“方法注冊(cè)的位置被限定死,而且沒有辦法反注冊(cè)”

我們注冊(cè)方法時(shí)是將方法名稱和方法體存放到一個(gè)map中,當(dāng)有方法被調(diào)用時(shí)會(huì)從map中找到對(duì)應(yīng)方法體并執(zhí)行,反注冊(cè)則是從map中移除該方法。

//flutter---
var _methodMap = HashMap<String, MethodHandler>();

// 注冊(cè)方法
void registerHandler(String methodName, MethodHandler methodHandle) {
_methodMap[methodName] = methodHandle;
}

// 反注冊(cè)方法
MethodHandler unregisterHandler(String methodName) {
return _methodMap.remove(methodName);
}
  
//native---
private val methodMap = hashMapOf<String, MethodHandler>()

/**
 * 注冊(cè)方法
 */
fun registerHandler(methodName: String, methodHandler: MethodHandler) {
    methodMap[methodName] = methodHandler
}

/**
 * 反 注冊(cè)方法
 */
fun unRegisterHandler(methodName: String): MethodHandler? {
    return methodMap.remove(methodName)
}

3. 解決“Native端的調(diào)用和回調(diào)必須保證在主線程”

我們會(huì)在調(diào)用和回調(diào)時(shí)判斷當(dāng)前線程,如果非主線程,則切換到主線程在進(jìn)行調(diào)用或回調(diào)。這樣開發(fā)者就不用擔(dān)心線程切換問題了

//調(diào)用 
    fun <R> callFlutter(
        methodName: String,
        params: Map<String, Any?> = HashMap(),
        callBack: HandleCallBack<R> = DefaultHandleCallBack<R>()
    ) {

        if (HandlerUtils.isMainThread()) {
            callFlutterInner(methodName, params, callBack)
        } else {
            HandlerUtils.getMainHandler().post {
                callFlutterInner(methodName, params, callBack)
            }
        }

    }
//回調(diào)
    fun success(result: Any?) {
        if (HandlerUtils.isMainThread()) {
            resultOrigin.success(result)
        } else {
            HandlerUtils.getMainHandler().post {
                resultOrigin.success(result)
            }
        }
    }

使用(更多使用可以前往github

flutter

//方法注冊(cè)
FlutterBridge.instance.registerHandler("getFlutterMap", (params) {
      print('getFlutterMap ${params.toString()}');
      return {
        "aa": "bb",
        "cc": 1,
        "dd": [1, 2, 3],
        "ee": true
      };
    });

 //方法調(diào)用
 MaterialButton(
      onPressed: () async {
        var map = await FlutterBridge.instance.callNative<Map>("callNativeReturnMap", params: {
          "aa": "bb",
          "cc": 1,
          "dd": [1, 2, 3],
          "ee": true
        });
        result = map.toString();
        setState(() {});
      },
      child: Text("調(diào)用原生方法-帶入?yún)?返回值是map"),
    )

原生

//方法注冊(cè)
FlutterBridge.instance.registerHandler("callNativeReturnMap",
    object : MethodHandlerHaveReturn<Map<String, Any>> {
        override fun onMethodCall(params: Map<String, Any?>): Map<String, Any> {

            Log.e("flutterBridge","callNativeReturnMap params =${params.toString()}")

            return hashMapOf(
                "aa" to "bb",
                "cc" to 1,
                "dd" to arrayListOf(1, 2, 3),
                "ee" to true
            )
        }
    })
//方法調(diào)用
 findViewById<View>(R.id.btn_map).setOnClickListener {
    FlutterBridge.instance.callFlutter(
        "getFlutterMap",
        params = hashMapOf(
            "aa" to "bb",
            "cc" to 1,
            "dd" to arrayListOf(1, 2, 3),
            "ee" to true
        ),
        callBack = object : HandleCallBack<Map<String, Any?>> {
            override fun callSuccess(result: Map<String, Any?>?) {
                tv.text = "調(diào)用flutter方法-帶入?yún)?返回Map result=${result.toString()}"
            }

        })

}

操作演示

flutter-native.gif
native-flutter.gif

GitHub地址

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容