Доступ к пользовательскому интерфейсу из JavaScript на Android - PullRequest
6 голосов
/ 25 февраля 2012

По некоторым причинам мне приходится использовать WebView в моем приложении Android, и часть бизнес-логики содержится в JavaScript (я запускаю его с помощью addJavascriptInterface ()). Проблема в том, что я не могу изменить компоненты пользовательского интерфейса моего приложения из объекта, связанного со сценарием. Это объясняется в документации:

Примечание. Объект, связанный с вашим JavaScript, запускается в другом нить, а не нить, в которой он был построен.

Мне интересно, есть ли какое-нибудь решение этой проблемы?

Ответы [ 2 ]

14 голосов
/ 25 февраля 2012

Вам необходимо передать экземпляр Handler в ваш интерфейс JavaScript и использовать его для публикации там исполняемых объектов.Если этот обработчик будет создан в потоке пользовательского интерфейса, runnables , размещенные там , также будут вызваны в потоке пользовательского интерфейса.

Handler mHandler = new Handler(); // must be created on UI thread, e.g. in Activity onCreate

// from javascript interface...
mHandler.post(new Runnable() {
    @Override
    public void run() {
        // code here will run on UI thread
    }
});

Другой обходной путь - использовать метод Activity runOnUIThread

mActivity.runOnUIThread(new Runnable() {
    @Override
    public void run() {
       // code here will run on UI thread
    }
});
1 голос
/ 03 июня 2012

Предположим, вы находитесь внутри фрагмента и делаете getActrivity().runOnUIThread(...) в своем коде интерфейса Javascript. Возможно, что к тому моменту, когда WebViewCoreThread выполнит код интерфейса Javascript, фрагмент отсоединится от действия, и getActivity () вернет значение null, что приведет к созданию исключения NullPointerException. Безопасный способ сделать это - использовать обработчик, как в примере ниже. Кроме того, убедитесь, что интерфейс JavaScript использует WeakReferences для компонентов пользовательского интерфейса, если они должны быть подвергнуты сборке мусора перед выполнением интерфейса Javascript.

 myWebView.addJavascriptInterface(new Object() {
        private Handler handler = new Handler();
        private WeakReference<ProgressBar> progressBarRef = new WeakReference<ProgressBar>(
                myWebViewProgressBar);
        private WeakReference<WebView> myWebViewRef = new WeakReference<WebView>(
                myWebView);

        @SuppressWarnings("unused")
        public void onFirstImageLoad() {

            handler.post(new Runnable() {
                @Override
                public void run() {
                    ProgressBar progressBar = progressBarRef.get();
                    WebView webView = myWebViewRef.get();
                    if (progressBar != null) {
                        progressBar.setVisibility(View.GONE);
                    } 
                    if (webView != null) {
                        webView .setVisibility(View.VISIBLE);
                    }
                }
            });
        }
    }, "jsInterface");
...