如何在 Android 中等待异步 API?
How to wait for async APIs in Android?
在android
中,有很多async APIs
比如WebView的evaluateJavascript
,会Asynchronously
在当前显示页面的上下文中求值JavaScript
.通常,在调用 async API 之后,执行将继续执行后续语句,而无需任何等待。
但是在继续 successive statements
之前,我如何才能 等待 直到此调用完成执行。例如,
webview.evaluateJavascript("JS code", new ValueCallback<String> {
public void onReceiveValue(String value) {
//get JS return here
}
});
//Remaining code
如何确保在 webview.evaluateJavascript
完成执行后执行剩余代码(即,其回调 onReceiveValue
已完成执行)。
编辑:更准确地说,我想要的是剩余的代码应该在 onReceiveValue 完成执行后执行。
当您必须等待代码执行时,一个简单的 class 可以使用的是 CountDownLatch。
您的问题的示例可以是:
public class AboutActivity extends Activity {
private volatile CountDownLatch jsLatch = new CountDownLatch(1);
private volatile String jsReceivedValue = null
initWebView() {
// webview init
...
webview.evaluateJavascript("JS code", new ValueCallback<String> {
public void onReceiveValue(String value) {
//get JS return here
jsReceivedValue = value
jsLatch.countDown();
}
});
try {
// wait 60 seconds or assume there was some problem during the loading
jsLatch.await(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// thread interrupted or time elapsed
}
if (jsReceivedValue == null) {
// show "problem during loading"
} else {
//Remaining code
}
}
}
请注意,在主线程上等待代码执行可能会导致应用无响应。
您可以在使用简单线程时显示加载微调器来避免这种情况:
new Thread(new Runnable() {
@Override
public void run() {
initWebView();
}
}).start();
我通过使用 Java脚本界面找到了解决方法。这个想法是我们创建一个桥 class,其中包含一个将 javascript 执行结果作为输入的方法。那么我们就可以得到Java端的结果了。此方法之所以有效,是因为桥接方法由 Java 脚本代码调用,该脚本代码在另一个线程上 运行。我们只需要在 UI 线程上等待几毫秒,结果就在这里。以下代码为例:
class Bridge {
public String result = null;
@JavascriptInterface
public void putJsResult(String result) {
this.result = result;
}
public String getJsResult() {
return this.result;
}
}
Bridge bridge = new Bridge();
wv.addJavascriptInterface(bridge, "bridge");
webview.evaluateJavascript("bridge.putJsResult(func())", null);
Thread.sleep(100);
//Result is there
String result = bridge.getJsResult();
在android
中,有很多async APIs
比如WebView的evaluateJavascript
,会Asynchronously
在当前显示页面的上下文中求值JavaScript
.通常,在调用 async API 之后,执行将继续执行后续语句,而无需任何等待。
但是在继续 successive statements
之前,我如何才能 等待 直到此调用完成执行。例如,
webview.evaluateJavascript("JS code", new ValueCallback<String> {
public void onReceiveValue(String value) {
//get JS return here
}
});
//Remaining code
如何确保在 webview.evaluateJavascript
完成执行后执行剩余代码(即,其回调 onReceiveValue
已完成执行)。
编辑:更准确地说,我想要的是剩余的代码应该在 onReceiveValue 完成执行后执行。
当您必须等待代码执行时,一个简单的 class 可以使用的是 CountDownLatch。 您的问题的示例可以是:
public class AboutActivity extends Activity {
private volatile CountDownLatch jsLatch = new CountDownLatch(1);
private volatile String jsReceivedValue = null
initWebView() {
// webview init
...
webview.evaluateJavascript("JS code", new ValueCallback<String> {
public void onReceiveValue(String value) {
//get JS return here
jsReceivedValue = value
jsLatch.countDown();
}
});
try {
// wait 60 seconds or assume there was some problem during the loading
jsLatch.await(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// thread interrupted or time elapsed
}
if (jsReceivedValue == null) {
// show "problem during loading"
} else {
//Remaining code
}
}
}
请注意,在主线程上等待代码执行可能会导致应用无响应。 您可以在使用简单线程时显示加载微调器来避免这种情况:
new Thread(new Runnable() {
@Override
public void run() {
initWebView();
}
}).start();
我通过使用 Java脚本界面找到了解决方法。这个想法是我们创建一个桥 class,其中包含一个将 javascript 执行结果作为输入的方法。那么我们就可以得到Java端的结果了。此方法之所以有效,是因为桥接方法由 Java 脚本代码调用,该脚本代码在另一个线程上 运行。我们只需要在 UI 线程上等待几毫秒,结果就在这里。以下代码为例:
class Bridge {
public String result = null;
@JavascriptInterface
public void putJsResult(String result) {
this.result = result;
}
public String getJsResult() {
return this.result;
}
}
Bridge bridge = new Bridge();
wv.addJavascriptInterface(bridge, "bridge");
webview.evaluateJavascript("bridge.putJsResult(func())", null);
Thread.sleep(100);
//Result is there
String result = bridge.getJsResult();