I understand what the CalledFromWrongThreadException exception means, but I cannot comprehend how the code I have written isn’t executing on the uithread in this situation.
In my main activity I create a handler.
private final Handler handler = new AppHandler(this);
In the onCreateDialog method of the activity, I was using the constructor suggested by the android examples of timepicker dialogues. Since I was getting the CalledFromWrongThreadException in a way I didn’t understand and wasn’t reproducible on my devices or the emulator, I tried to pass a reference of my activity in to the create dialogue constructor.
So my code to create the dialog looks like this.
@Override
protected Dialog onCreateDialog(int id) {
final Calendar c = Calendar.getInstance();
switch (id) {
case TIME_DIALOG_ID:
return new TimePickerDialog(this, this, getHandler(),
mTimeSetListener, c.get(Calendar.HOUR_OF_DAY),
0, false);
The first instance of “this” gets used as a Context by the dialog, the second instance gets stored off as an Activity.
The dialog itself is the android sample code but I have been attempting to fix the threading problems I’m seeing.
Then inside of the dialog where I am having threading issues. I use the main activity and try to use its handler to execute the setTitle command as a runnable.
mainactivity.getHandler().post(new Runnable() {
public void run() {
setTitle(mDateFormat.format(mCalendar.getTime()));
}
});
Edit: Changing the code so that the attempt to run on the ui thread is using the method on the main activity instead of the handler produces the same results.
mainactivity.runOnUiThread(new Runnable() {
public void run() {
setTitle(mDateFormat.format(mCalendar.getTime()));
}
});
Here’s a copy of a stacktrace:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRoot.checkThread(ViewRoot.java:3214)
at android.view.ViewRoot.invalidateChild(ViewRoot.java:681)
at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:707)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511)
at android.view.View.invalidate(View.java:5418)
at android.widget.TextView.checkForRelayout(TextView.java:5750)
at android.widget.TextView.setText(TextView.java:2866)
at android.widget.TextView.setText(TextView.java:2727)
at android.widget.TextView.setText(TextView.java:2696)
at com.android.internal.app.AlertController.setTitle(AlertController.java:222)
at android.app.AlertDialog.setTitle(AlertDialog.java:100)
at com.testapp.TimePickerDialog$1.run(TimePickerDialog.java:159)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3691)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
at dalvik.system.NativeStart.main(Native Method
Also note that I use this same handler all over my app to successfully execute things on the UI thread.
Any suggestions on other approaches I might try or tips to debug this would be greatly appreciated.
Thanks!
In the end the issue is that I was calling showDialog() from a thread that was not the ui thread.
I figured out the issue when reading android dev blog on memory leaking and realized that I had passed a handle to the activity beyond where it should be.
I’m now calling showDialog() from inside of the runOnUiThread of the main activity as sonu pointed out and everything seems to be working.