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

Java中WebView调用JS函数回调延迟问题及解决方案咨询

解决WebView异步调用JS获取返回值的问题

你遇到的问题核心是**evaluateJavascript是异步执行的**——Java代码会直接往下走,不会等待JS执行完回调再运行后续的if判断,所以后续代码执行时,回调还没触发,jsonStringTagResult自然还是null。以下是几种可行的处理方案:

方案1:把后续逻辑移到回调内部(最推荐)

所有需要用到JS返回值的代码,都必须放在onReceiveValue方法里,或者从这里调用专门处理结果的方法,因为这个方法是JS执行完成后才会触发的。

修改后的代码示例:

// 直接把后续逻辑移到回调里
webView.evaluateJavascript("patrolTagToInvoke('"+tagId+"')", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String value) {
        // 这里能保证拿到JS返回的有效值
        if (value != null && !value.isEmpty()) {
            // 处理value的逻辑写在这里
            // 比如解析JSON、更新UI等
        }
    }
});

如果逻辑比较复杂,也可以抽成单独的方法:

webView.evaluateJavascript("patrolTagToInvoke('"+tagId+"')", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String value) {
        handleJsResult(value);
    }
});

// 单独的处理方法
private void handleJsResult(String jsValue) {
    if (jsValue != null && !jsValue.isEmpty()) {
        // 执行后续逻辑
    }
}

方案2:用同步等待(不推荐,易阻塞主线程)

如果一定要让Java代码等待JS返回结果,可以用CountDownLatch,但绝对不能在主线程使用,否则会导致ANR(应用无响应),必须放在子线程里执行:

new Thread(() -> {
    CountDownLatch latch = new CountDownLatch(1);
    String[] jsonStringTagResult = new String[1];

    webView.post(() -> {
        webView.evaluateJavascript("patrolTagToInvoke('"+tagId+"')", new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String value) {
                jsonStringTagResult[0] = value;
                latch.countDown(); // 通知等待的线程可以继续
            }
        });
    });

    try {
        latch.await(); // 等待JS回调完成
        // 这里可以拿到结果了
        if (jsonStringTagResult[0] != null && !jsonStringTagResult[0].isEmpty()) {
            // 处理逻辑
            // 注意如果要更新UI,需要切回主线程
            runOnUiThread(() -> {
                // 更新UI操作
            });
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

注意:这种方式会占用线程资源,而且如果JS执行超时,会一直阻塞线程,所以尽量不用。

方案3:用JavascriptInterface让JS主动传值(更灵活的替代方案)

可以把一个Java对象注入到WebView的JS环境中,让JS执行完后主动调用这个对象的方法把结果传回来,这种方式比evaluateJavascript更灵活,尤其适合复杂交互场景。

步骤1:定义带注解的Java类

public class JsBridge {
    // Android 4.2及以上必须加@JavascriptInterface注解,否则JS无法调用
    @JavascriptInterface
    public void onPatrolTagResult(String result) {
        // 这里直接拿到JS传递的结果
        if (result != null && !result.isEmpty()) {
            // 处理逻辑,注意如果要更新UI,需要切回主线程
            runOnUiThread(() -> {
                // 更新UI或其他操作
            });
        }
    }
}

步骤2:注入对象到WebView

WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
// 把JsBridge对象注入到JS环境,JS里可以通过"AndroidBridge"这个名字调用它的方法
webView.addJavascriptInterface(new JsBridge(), "AndroidBridge");

步骤3:修改JS代码,主动调用Java方法

让你的patrolTagToInvoke函数执行完后,调用AndroidBridge.onPatrolTagResult把结果传回来:

function patrolTagToInvoke(tagId) {
    // 原来的逻辑,获取结果
    var result = "你的返回值";
    // 主动调用Java方法传值
    window.AndroidBridge.onPatrolTagResult(result);
}

注意:如果你的JS函数是有返回值的,也可以保持原来的逻辑,同时添加主动传值的代码,不影响原有功能。

内容的提问来源于stack exchange,提问作者Gabriel Palmeri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 20:20:26