Reputation: 23371
I am developing on a library that is somehow getting a CalledFromWrongThread
Exception crash on Samsung Galaxy S1 (api v7 - android 2.1). The code is something like this:
class MyWebViewClient extends WebViewClient {
@Override
public void shouldOverrideUrlLoading(WebView view, String url) {
someListener.addToUiView();
}
}
and of course, the method that is actually throwing the error (which implements a listener callback):
View v;
public void addToUiView(){
v.addView(new TextView(context)); //<-- this line is throwing the error on rare occasions
}
I'm skipping some code in between, but i'm not doing anything weird in other places. Also note: this crash only seems to have been happening a very very small % of the time. (not necessarily conclusive, as not everyone reports their data).
has anyone else come across this?? Is WebCore threading messing things up?
Upvotes: 2
Views: 439
Reputation: 6761
Now I haven't actually tested this but I am going to answer to the best of my knowledge. That said, my instinct is telling me that you are only seeing the error intermittently because web requests from a WebView
(browser) happen with varying levels of asynchronicity and probably utilize a thread pool to accomplish this. Basically, sometimes it requests resources in parallel and sometimes it doesn't. Worse yet you might be seeing this error on only a single device because OEMs optimize OS level code (like the WebView
internals) based on their preferences and opinions (especially Samsung). Either way the real problem is that you are doing something "UI related" in a place that is definitely not guaranteed to be "UI friendly"... That is, anywhere where you are getting a subsystem callback.
The solution to your problem is much more simpler than the explanation: just use your context
(that I am assuming is an Activity
)..
Activity
s have a built in function called runOnUiThread(Runnable)
that will guard the code inside the runnable from running on the wrong thread. Basically, your problem is really common and android has a built-in solution. runOnUiThread
will only add overhead if required, in other words if your thread is the UI thread, it will just run the Runnable
, if it isn't it uses the correct Handler
(the one associated with the UI thread) to run the Runnable
.
Here is what it should look like:
View v;
public void addToUiView() {
final Activity activity = (Activity) context;
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
v.addView(new TextView(activity));
}
});
}
i coded that up right inside the SO window so my apologies for any egregious errors, I hope that helps, and let me know if you need more info or of this doesn't solve your problem -ck
Upvotes: 2