引言
在现代前端开发中,尤其是移动端混合开发,前端与原生应用之间的通信是一个常见需求。 为了解决这个问题,我们可以使用一个桥接类 AppBridge,它封装了调用原生方法和处理原生回调的逻辑。
为什么需要 AppBridge
在 WebView 中直接调用原生方法,如果每次都写原生平台判断和回调处理,代码会非常混乱。而 AppBridge 的出现正是为了:
- 提供统一的调用接口
- 自动处理回调,支持 Promise
- 兼容 iOS 和 Android
- 支持开发环境日志输出,方便调试
核心设计
单例模式
1 2 3 4 5 6
| public static getInstance(): AppBridge { if (!AppBridge.instance) { AppBridge.instance = new AppBridge(); } return AppBridge.instance; }
|
使用单例模式保证全局只有一个桥接实例,避免重复注册回调函数。
核心属性
1 2 3 4 5 6 7 8
| private static instance: AppBridge; private __callbacks: { [key: string]: { resolve: (value: any) => void; reject: (reason?: any) => void; method: string; }; } = {};
|
instance:存储单例实例
__callbacks:存储调用原生方法的回调函数
调用原生方法
1
| callNative<P, R>(method: string, params: P): Promise<R>
|
调用流程:
生成唯一 callbackId
将 Promise 的 resolve 和 reject 存入 __callbacks
构造调用数据
根据平台调用原生方法:
- iOS 使用
window.webkit.messageHandlers.xxCallNative.postMessage
- Android 使用
window.xxx.xxCallNative
1 2 3 4 5 6
| # Android 端接收 web 端调用示例 @JavascriptInterface fun xxCallNative(data: String){}
# Android 端调用 web 端示例 webView.evaluateJavascript("javascript:xxCallWeb('$json')", null);
|
非原生环境:
初始化回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| private initBridgeCallback() { const oldCallback = window.ddCallWeb; window.ddCallWeb = (callbackData: string) => { const data = JSON.parse(callbackData); if (this.log) console.info("nativeInvoke:", data);
if (isFunction(oldCallback)) oldCallback(data);
const { callbackId } = data; const callback = this.__callbacks[callbackId];
if (callback) { if (data.code === 0) callback.resolve(data.data); else { const error = new Error(data.msg) as Error & { response: unknown }; error.response = data; callback.reject(error); } this.__callbacks = omit(this.__callbacks, callbackId); } else { this.dispatchNativeInvoke(data.method, data.params); } }; }
|
自动接收原生调用,将对应回调函数执行或者分发事件。
原生调用分发
1 2 3 4 5 6 7 8 9 10 11
| private dispatchNativeInvoke = (method: string, params: any) => { switch (method) { case "route": const path = params.router; const type = params.type; type === "push" ? router.push(path) : router.replace(path); break; default: console.warn(`未处理的原生方法调用: ${method}`, params); } };
|
使用示例
1 2 3 4 5 6 7 8 9
| const bridge = AppBridge.getInstance();
bridge.callNative("getUserInfo", { userId: 123 }) .then(res => console.log("用户信息:", res)) .catch(err => console.error("调用失败:", err));
emitter.on("onActivated", ({ route }) => { console.log("页面激活:", route); });
|
总结
AppBridge 提供了一个干净、统一的桥接方案,让前端调用原生方法和处理原生事件变得简单。其特点:
- 单例模式,保证全局唯一
- Promise 风格,链式调用和错误处理简单
- 自动回调处理,兼容 iOS/Android
- 可扩展性强,只需在
dispatchNativeInvoke 添加 case