You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 19:03:18