来自Android WebView的异步JavaScript调用

Guy*_*gal 8 javascript android webview

我正在使用WebView构建混合Android应用程序,该应用程序通过JavaScriptInterface注释与设备进行通信

从WebView:

webView.addJavascriptInterface(someService, "someService");
Run Code Online (Sandbox Code Playgroud)

服务实施:

@JavascriptInterface
public void someMethod() {
    //do some business logic..
}
Run Code Online (Sandbox Code Playgroud)

问题是我从JavaScript运行它是这样的:

function callSomeMethod() {
    someService.someMethod()
};
Run Code Online (Sandbox Code Playgroud)

这个调用是同步的,并且想要一些异步运行的东西,如:

function callSomeMethod(callback) {
    someService.someMethod(function(result) {
        if (result == 'success')
            callback();
    })
};
Run Code Online (Sandbox Code Playgroud)

最好使用承诺:

function callSomeMethod() {
    return someService.someMethod()
    //someMethod returns promise
};
Run Code Online (Sandbox Code Playgroud)

Android WebView是否内置支持异步运行JavaScript代码?

Mik*_*nov 5

这完全取决于你.您只需要从注入的方法立即返回,但能够在执行完成时调用JS代码.像这样的东西(注意它只是一个粗略的草图):

private WebView mWebView;
private final Object mLock = new Object();
private String mJsCallbackCode;

@JavascriptInterface
public void someMethod(String jsCallbackCode) {
    synchronized (mLock) {
        mJsCallbackCode = jsCallbackCode;
    }
    // Start some business logic asynchronously, and return back here immediately.
    return;
}

public void onBusinessLogicCompleted(bool success) {
    String jsCallbackCode;
    synchronized (mLock) {
        jsCallbackCode = mJsCallbackCode;
    }
    mWebView.loadUrl("javascript:" + jsCallbackCode + "(" + success + ");void(0);");
}
Run Code Online (Sandbox Code Playgroud)

在JavaScript中,您可以像这样使用它:

function callSomeMethod(callback) {
    window._someMethodCallback = callback;
    someService.someMethod(
        '(function(success){' +
        '    if (success) window._someMethodCallback();' +
        '    delete window._someMethodCallback;' +
        '})'
    );
};    
Run Code Online (Sandbox Code Playgroud)

所以我的想法是你传递需要作为字符串回调的JS代码(因为你无法传递真正的JS对象).此代码将在全局上下文中调用.

需要锁定Java,因为从JS调用的方法在专用线程上运行,而不是在应用程序的UI线程上运行.

请注意,在M预览中,postMessage已将一个API 添加到WebView,从而能够在Java和JS代码之间发布异步消息.