Android WebView原生-Web桥接中回调参数始终为null问题
Android WebView 原生-Web桥接回调为null的解决方案
问题根源
Android WebView的@JavascriptInterface不支持直接接收JavaScript的函数作为参数,仅能处理基本数据类型(int、boolean等)、String、JSONObject、JSONArray这类可序列化的类型。Web端传入的函数会被桥接机制转为null,这就是你遇到回调始终为空的核心原因。
解决方案:回调ID映射机制
通过生成唯一回调ID,将Web端的回调函数存储在全局对象中,把ID传给原生;原生处理完成后,调用Web端的全局处理函数并传入ID和结果,Web端根据ID找到对应的回调执行。
1. 原生侧代码修改
class WebViewInterface(private val webView: WebView) { @JavascriptInterface fun testAsync(message: String, callbackId: String) { println("Async Message: $message") // 模拟异步操作(实际开发建议用协程或Handler,避免阻塞UI线程) Thread { Thread.sleep(2000) val processedResult = "处理后的结果:$message" // 回到UI线程调用Web端回调 webView.post { // 转义结果中的特殊字符,避免JS语法错误 val escapedResult = JSONObject.quote(processedResult) val jsCode = "window.handleNativeCallback('$callbackId', $escapedResult);" webView.evaluateJavascript(jsCode, null) } }.start() } @JavascriptInterface fun showToast(message: String) { // 实现showToast逻辑,比如调用Toast.makeText } } // 接口配置 webView.addJavascriptInterface(WebViewInterface(webView), "Hybrid")
2. Web端代码修改
// 全局存储回调函数,执行后及时清理避免内存泄漏 window.nativeCallbacks = {}; // 生成唯一回调ID的工具函数 function generateCallbackId() { return 'cb_' + Date.now() + Math.random().toString(36).slice(2, 11); } // 封装原生调用,自动处理回调ID映射 function callTestAsync(message, callback) { const callbackId = generateCallbackId(); window.nativeCallbacks[callbackId] = callback; Hybrid.testAsync(message, callbackId); } // 原生调用的统一回调处理函数 window.handleNativeCallback = function(callbackId, result) { const callback = window.nativeCallbacks[callbackId]; if (callback) { callback(result); // 执行后删除回调,释放内存 delete window.nativeCallbacks[callbackId]; } }; // 测试按钮绑定逻辑 document.querySelector('#testBtn').addEventListener('click', () => { callTestAsync("Hello World", (message) => { Hybrid.showToast(message); }); });
关键注意事项
- 所有WebView的JS调用必须在UI线程执行,所以原生异步操作完成后要通过
webView.post()切换线程。 - 结果中的特殊字符(如单引号、换行、双引号)必须转义,否则会导致JS语法错误,推荐用原生的
JSONObject.quote()处理。 - 执行完回调后要从全局对象中删除对应的函数,避免Web端内存泄漏。
内容的提问来源于stack exchange,提问作者Jüri Kiin
相关产品推荐
相关产品推荐

