问题
I need to update my UI from an external Thread
. I can't use runOnUiThread, because it's an application using StandOut libraries.
So I created my Handler
in the class containing methods to update the UI:
private final class UIHandler extends Handler {
public static final int DISPLAY_UI_TOAST = 0;
private static final int LOAD_PROFILE = 1;
public UIHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UIHandler.DISPLAY_UI_TOAST: {
Context context = mw.getApplicationContext();
Toast t = Toast.makeText(context, (String) msg.obj,
Toast.LENGTH_SHORT);
t.show();
}
case UIHandler.LOAD_PROFILE:{
loadProfile((String) msg.obj);
}
default:
break;
}
}
}
And I then I created a method to send messages to the Handler
public void loadP(String prof){
Message msg = uiHandler.obtainMessage(UIHandler.LOAD_PROFILE);
msg.obj = prof;
uiHandler.sendMessage(msg);
}
But when I call loadP(myProfile), the app crashes with this error:
08-25 19:55:08.428: E/AndroidRuntime(8602): FATAL EXCEPTION: UIHandler
08-25 19:55:08.428: E/AndroidRuntime(8602): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4607)
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:835)
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.view.View.requestLayout(View.java:15129)
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.view.View.requestLayout(View.java:15129)
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.view.View.requestLayout(View.java:15129)
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.view.ViewGroup.addView(ViewGroup.java:3249)
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.view.ViewGroup.addView(ViewGroup.java:3196)
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.view.ViewGroup.addView(ViewGroup.java:3172)
08-25 19:55:08.428: E/AndroidRuntime(8602): at com.vektor.amapper.elements.KeyElement.createButton(KeyElement.java:261)
08-25 19:55:08.428: E/AndroidRuntime(8602): at com.vektor.amapper.elements.KeyElement.setButton(KeyElement.java:159)
08-25 19:55:08.428: E/AndroidRuntime(8602): at com.vektor.amapper.elements.KeyElement.<init>(KeyElement.java:81)
08-25 19:55:08.428: E/AndroidRuntime(8602): at com.vektor.amapper.util.KeyElementManager.add(KeyElementManager.java:32)
08-25 19:55:08.428: E/AndroidRuntime(8602): at com.vektor.amapper.util.KeyElementManager.loadProfileUI(KeyElementManager.java:91)
08-25 19:55:08.428: E/AndroidRuntime(8602): at com.vektor.amapper.util.MapperController.loadProfileUI(MapperController.java:106)
08-25 19:55:08.428: E/AndroidRuntime(8602): at com.vektor.amapper.windows.ui.ProfilesPanel.loadProfile(ProfilesPanel.java:423)
08-25 19:55:08.428: E/AndroidRuntime(8602): at com.vektor.amapper.windows.ui.ProfilesPanel.access$1(ProfilesPanel.java:414)
08-25 19:55:08.428: E/AndroidRuntime(8602): at com.vektor.amapper.windows.ui.ProfilesPanel$UIHandler.handleMessage(ProfilesPanel.java:464)
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.os.Handler.dispatchMessage(Handler.java:99)
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.os.Looper.loop(Looper.java:137)
08-25 19:55:08.428: E/AndroidRuntime(8602): at android.os.HandlerThread.run(HandlerThread.java:60)
I want to add that the DISPLAY_UI_TOAST message is working.
回答1:
You need not extend all Handler
class if you just want to handle some messages, just implement Handler.Callback
:
private final class UICallback implements Handler.Callback{
public static final int DISPLAY_UI_TOAST = 0;
private static final int LOAD_PROFILE = 1;
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case UICallback.DISPLAY_UI_TOAST: {
Context context = mw.getApplicationContext();
Toast t = Toast.makeText(context, (String) msg.obj,
Toast.LENGTH_SHORT);
t.show();
return true;
}
case UICallback.LOAD_PROFILE:{
loadProfile((String) msg.obj);
return true;
}
default:
return false;
}
}
}
Note, in above code, true is returned when message is handled, false when message was not meant for us.
Now, create a handler with main looper (so that all messages run on UI thread ), and the callback we created:
Handler handler = new Handler(Looper.getMainLooper(),new UICallback());
回答2:
Refer below links you can get some ideas...
Android: got CalledFromWrongThreadException in onPostExecute() - How could it be?
Android CalledFromWrongThreadException
Can't resolve CalledFromWrongThreadException with Handler
CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch views
Handler changing UI causes CalledFromWrongThreadException
来源:https://stackoverflow.com/questions/18428715/update-ui-through-handler