為什么會(huì)開(kāi)發(fā)這個(gè)框架
在flutter和Native混合開(kāi)發(fā)的過(guò)程中我們難免會(huì)遇到flutter和Native相互通信的場(chǎng)景豪硅,這時(shí)我們就會(huì)用到flutter提供的 Flutter Platform Channel
能力。大部分情況我們使用的都是 MethodChannel
挺物,一般我們會(huì)這樣是用懒浮。
flutter中使用methodchannel
//聲明 methodchannel
static const MethodChannel LUXURY_METHOD_CHANNEL = MethodChannel('flutter_native_channel');
//注冊(cè)方法監(jiān)聽(tīng)
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)聽(tīng)
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ì)有哪些不方便或者問(wèn)題呢?
- 使用前必須要手動(dòng)聲明一個(gè)
MethodChannel
识藤,這也太麻煩了砚著。(手動(dòng)狗頭) - 方法注冊(cè)的位置被限定死,必須要在 MethodCallHandler的 onMethodCall 中聲明蹋岩,而且沒(méi)有辦法反注冊(cè)赖草。
- Native端的調(diào)用和回調(diào)必須保證在主線程。
基于這些問(wèn)題于是就有了flutter_bridge
.
如何封裝
1. 解決“必須要手動(dòng)聲明一個(gè)MethodChannel
問(wèn)題”
我們會(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è)的位置被限定死扣囊,而且沒(méi)有辦法反注冊(cè)”
我們注冊(cè)方法時(shí)是將方法名稱(chēng)和方法體存放到一個(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)惕虑。這樣開(kāi)發(fā)者就不用擔(dān)心線程切換問(wè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()}"
}
})
}