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
相关产品推荐
相关产品推荐

