引言
本文主要是简单叙述了如何实现一个与flutter通信的jsbridge。
js调用flutter
flutter需要用JavascriptChannel注册一个方法供js调用
JavascriptChannel(
name: "callFlutter",
onMessageReceived: (JavascriptMessage message) {
flutterHandle(message)
}
)
//toFlutterData的定义
{
method: string; //需要调用的方法名
param?: any; //参数需要根据每个需要的方法单独定义
callbackId: string; //回调的id
}
//js的调用
window['callFlutter'] && window['callFlutter'].postMessage(JSON.stringify(toFlutterData));
这里js的通信需要使用上面定义的callFlutter的postMessage的方式。flutterHandle需要根据method和param去调用对应的方法,结束后就通过主动调用js的方式完成回调。
flutter调用js
通过WebViewController调用evaluateJavascript方法,即可调用JS。evaluateJavascript类似于js中的eval函数,作用就是执行一段js的代码。js可以在bridge初始化的过程中在全局增加一个flutterCallback的函数,该函数的入参可以如下定义
export interface flutterCallbackParam {
result: number;//状态码标记是否成功
msg: string;
callbackId: string; //回调的id
data?: any;//回调结果
}
当然flutter需要把flutterCallbackParam也转为json,这样整个js调用flutter的过程就可以完成了,而flutter主动调用js的过程就是上面的逆过程。
jsBridge
桥的代码其实大都类似
jsBridge({methodName, params, success, fail}) {
const callbackID = randomCallbackID(actionID);//生成回调id
cachedPromise.set(callbackID, { success, fail });//回调池的注册
const toFlutterData = {
method:methodName,
callbackId: callbackID,
data: params
});
window['callFlutter'] && window['callFlutter'].postMessage(JSON.stringify(toFlutterData));
}
//也可以选择用比较方便的promise的方式
jsBridgePromise({methodName, params}) {
const callbackID = randomCallbackID(actionID);
return new Promise((resolve, reject) => {
cachedPromise.set(callbackID, { resolve, reject });
const toFlutterData = ({
method: methodName,
callbackId: callbackID,
data: params
});
window['callFlutter'] && window['callFlutter'].postMessage(JSON.stringify(toFlutterData));
});
之后只要和flutter端约定好methodName和对应的参数格式,在上面的代码之后在包装后的代码就可以暴露给业务使用了。
其他
- 需要兼容其他环境的bridge,最好的方式就是flutter的桥包装在原有的桥上,然后根据环境判断直接抹平差异,当然这就需要对应的函数和入参的定义接近
- 需要增加一些兜底判断和错误捕获,保证桥的稳定性
- 版本控制
总结
目前整个过程还没有实际的做线上实验,所以对于上述的通信效率和问题,还没有一个很好的认识,但基于目前的实现方式,很大程度上会面临和小程序类似的痛点,就是data的数据不能太大,对象转json非常消耗性能,另外就是大量调用的过程中,flutter如何做好批处理的回调也将会是痛点