2015-06-13 2 views
3

Я здание гибридной Android приложения с WebView, который взаимодействует с устройством с JavaScriptInterface аннотациюAsynchronous JavaScript звонки из Android WebView

От WebView:

webView.addJavascriptInterface(someService, "someService"); 

Реализация сервиса:

@JavascriptInterface 
public void someMethod() { 
    //do some business logic.. 
} 

Проблема в том, что из JavaScript я запускаю его следующим образом:

function callSomeMethod() { 
    someService.someMethod() 
}; 

Этот вызов является синхронным, и хотел бы что-то, что будет работать асинхронно, как:

function callSomeMethod(callback) { 
    someService.someMethod(function(result) { 
     if (result == 'success') 
      callback(); 
    }) 
}; 

Предпочтительно используя обещание:

function callSomeMethod() { 
    return someService.someMethod() 
    //someMethod returns promise 
}; 

ли Android WebView имеет встроенную поддержку для выполнения кода JavaScript асинхронно ?

ответ

4

Это зависит только от вас. Вам просто нужно немедленно вернуться из введенного метода, но иметь возможность вызывать 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);"); 
} 

И в JavaScript вы используете это так:

function callSomeMethod(callback) { 
    window._someMethodCallback = callback; 
    someService.someMethod(
     '(function(success){' + 
     ' if (success) window._someMethodCallback();' + 
     ' delete window._someMethodCallback;' + 
     '})' 
    ); 
};  

Так идея заключается в том, что вы передаете код JS вы должны быть вызываемый назад как строка (потому что вы не можете передать реальный объект JS). Этот код будет вызываться в глобальном контексте.

Блокировка на Java необходима, потому что методы, вызванные JS, запускаются в выделенном потоке, а не в потоке пользовательского интерфейса вашего приложения.

Обратите внимание, что в режиме предварительного просмотра M в WebView добавлен API для postMessage, позволяющий размещать асинхронные сообщения между Java и JS-кодом.