Подтвердить что ты не робот

Как WebView.getTitle() из потока пользовательского интерфейса?

В подклассе WebView я использовал эту строку в переопределенном методе getTitle():

String title = super.getTitle();

Он хорошо работал во всех версиях Android, пока я не смог проверить свое приложение на телефоне Android 4.1, что дало мне это предупреждение в этой строке super.getTitle()

12-20 21: 38: 27.467: W/webview_proxy (2537): java.lang.Throwable: Внимание: в потоке 'WebViewCoreThread' был вызван метод WebView. Все методы WebView должны вызываться в потоке пользовательского интерфейса. Будущие версии WebView могут не поддерживать использование в других потоках.

Итак, я думал об этом новом декрете, передав его через runOnUiThread():

Activity a = this.getActivity();
a.runOnUiThread(new Runnable() {
    public void run() { 
    String title = super.getTitle();
    }
});

Но этот код даже не компилируется, потому что super больше не относится к WebView, а скорее к Activity.

Любая идея как super.getTitle() от потока пользовательского интерфейса? (с ограничениями, описанными выше, в getTitle() подкласса WebView)

4b9b3361

Ответ 1

Morgan answer, хотя он может исправить ошибку компиляции, на самом деле не является решением этой проблемы.

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

Вы скажете в комментарии, что

Обстоятельства состоят в том, что я вызываю его в WebViewClient.onPageFinished(), который, случается, не находится в потоке пользовательского интерфейса.

Это может быть проблемой. Если вы начинаете веб-запрос из потока пользовательского интерфейса, то onPageFinished() обязательно должен быть вызван обратно в поток пользовательского интерфейса. Можете ли вы объяснить, как вы начинаете веб-запрос, и почему вы это делаете? В большинстве случаев вы не должны видеть onPageFinished() в фоновом режиме, поэтому у вас может быть проблема в другом месте.

(Примечание: если вы считаете, что вам нужно вызвать WebView.loadUrl() в фоновом режиме, чтобы избежать блокировки пользовательского интерфейса, см. этот другой ответ на эту проблему)

Если, вы действительно думаете, что вам нужно запустить веб-запрос в фоновом режиме, и вы видите onPageFinished(), вызванный в фоновом режиме, вам нужно позаботиться о вызове getTitle() в потоке пользовательского интерфейса.

Кроме того, если вы вызываете его из метода onPageFinished(), тогда нет необходимости использовать синтаксис, подобный этому:

String title = MyWebView.this.getTitle();

в этом методе вы передаете экземпляр своего веб-представления, поэтому просто используйте его напрямую:

public void onPageFinished (WebView view, String url) {
    String title = view.getTitle();
}

но, как я уже сказал, это не касается проблемы с потоками. Вам нужно будет показать нам , почему вы пытаетесь использовать заголовок страницы в этом методе, но один из способов безопасного его использования будет примерно таким:

public void onPageFinished (final WebView view, String url) {
   view.post(new Runnable() {
      public void run() { 
         String title = view.getTitle();
         // do something with title that affects the UI here
      }
   });     
}

Примечание, что мне нужно было сделать параметр view final в приведенном выше коде.

Ответ 2

У меня нет прямого ответа на ваш вопрос, но я могу предложить обходной путь, который работал у меня, когда я столкнулся с аналогичной проблемой: найдите метод, вызывающий метод, вызывающий String title = super.getTitle();, и запустите it через runOnUiThread().

НТН.

Ответ 3

Прямое решение состоит в том, чтобы сделать это

String title = MyWebView.this.getTitle();

вместо

String title = super.getTitle();

Как было сказано, было бы интересно узнать больше об обстоятельствах, при которых вы это называете (I.e., почему вы называете это в фоновом режиме). Я спрашиваю, потому что я не уверен, что ваш подход будет делать то, что вы хотите, даже после того, как вы измените код, о котором я упоминал.

Ответ 4

Чтобы избавиться от этого предупреждения, вы делаете следующее:

  Handler handler =new Handler();
    handler.post(new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            String URL = "http://www.superlinux.net";

            //Of course the object "webview" is a WebView. 
            //it better to define it a global variable
            webview.loadUrl(URL);
        }
    });

Поэтому, используя этот способ, поскольку webview является элементом пользовательского интерфейса, вы используете объект Handler. Обработчики - это своего рода потоки, которые выполняются отдельно от создания любого элемента пользовательского интерфейса.