Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to WebView.getTitle() from a UI thread?

In a subclass of WebView, I used to have this line in an overridden method of getTitle():

String title = super.getTitle();

It worked well in all versions of Android, until I got to test my app on an Android 4.1 phone, which gave me this warning on that super.getTitle() line:

12-20 21:38:27.467: W/webview_proxy(2537): java.lang.Throwable: Warning: A WebView method was called on thread 'WebViewCoreThread'. All WebView methods must be called on the UI thread. Future versions of WebView may not support use on other threads.

So, I was thinking of working around this new decree by passing it through runOnUiThread():

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

But this code won't even compile because super no longer refers to WebView, but rather to Activity.

Any idea how How to super.getTitle() from the UI thread? (with the constraints described above, in the getTitle() of a subclass of WebView)

like image 756
scatmoi Avatar asked Dec 21 '12 02:12

scatmoi


1 Answers

Morgan's answer, while it may fix the compile error, is not really a solution to this problem.

First of all, it does nothing to change the call to getTitle() to a different thread. That underlying issue is why Android is giving you the error at runtime.

You say in a comment that

The circumstances are that I am calling it in WebViewClient.onPageFinished(), which happens not to be on the UI thread.

That may be a problem. If you are starting the web request from the UI thread, then onPageFinished() should certainly get called back on the UI thread. Can you explain how you are starting the web request, and why you're doing it that way? The vast majority of the time, you shouldn't be seeing onPageFinished() called in the background, so you may have a problem elsewhere.

(Note: if you think you need to call WebView.loadUrl() in the background to avoid blocking the UI, please see this other answer on that issue)

If you really think you need to start the web request in the background, and you see onPageFinished() called in the background, you need to take care to call getTitle() on the UI thread.

Also, if you are calling it from the onPageFinished() method, then there is no need to use syntax like this:

String title = MyWebView.this.getTitle();

in that method, you are passed the instance of your web view, so just use it directly:

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

but, as I said, that doesn't address the threading issue. You would need to show us why you are trying to use the page title in that method, but one way to safely use it would be something like this:

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
      }
   });     
}

Note that I needed to make the view parameter final in the above code.

like image 50
Nate Avatar answered Nov 15 '22 20:11

Nate