UI update through a handler

I need to update my interface with external Thread . I cannot use runOnUiThread because it is an application using StandOut libraries.

So, I created my Handler in a class containing methods for updating the user interface:

 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 then I created a method for sending messages in 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 application 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.

0
source share
2 answers

You do not need to extend the entire Handler class, if you just want to handle some messages, just do 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; } } } 

Please note that in the above code it returns true when the message is being processed, false when the message is not intended for us.

Now create a handler with the main looper (so that all messages run in the user interface thread) and the callback that we created:

 Handler handler = new Handler(Looper.getMainLooper(),new UICallback()); 
+1
source

All Articles