Android TimePicker SetTitle UIThread问题

时间:2012-01-13 12:30:57

标签: android

我理解CalledFromWrongThreadException异常的含义,但我无法理解在这种情况下我编写的代码是如何在uithread上执行的。

在我的主要活动中,我创建了一个处理程序。

private final Handler handler = new AppHandler(this);

在活动的onCreateDialog方法中,我使用了timepicker对话框的android示例建议的构造函数。由于我以一种我不理解的方式获取CalledFromWrongThreadException并且在我的设备或模拟器上无法重现,因此我尝试将我的活动的引用传递给创建对话构造函数。

所以我创建对话框的代码看起来像这样。

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

“this”的第一个实例被对话框用作Context,第二个实例作为Activity被存储起来。

对话框本身是android示例代码,但我一直在尝试修复我看到的线程问题。

然后在我遇到线程问题的对话框里面。我使用main活动并尝试使用其处理程序将setTitle命令作为runnable执行。

    mainactivity.getHandler().post(new Runnable() {
        public void run() {
            setTitle(mDateFormat.format(mCalendar.getTime()));
        }
    });

编辑:更改代码,以便在ui线程上运行的尝试使用主活动而不是处理程序上的方法产生相同的结果。

    mainactivity.runOnUiThread(new Runnable() {
        public void run() {
            setTitle(mDateFormat.format(mCalendar.getTime()));
        }
    });

这是一个堆栈跟踪的副本:

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

另请注意,我在我的应用程序中使用相同的处理程序来成功执行UI线程上的内容。

对于我可能尝试的其他方法或调试此提示的任何建议都将非常感激。

谢谢!

2 个答案:

答案 0 :(得分:1)

使用

runOnUiThread(new Runnable() {

            @Override
            public void run() {
  //UI CODES
 }});

修改

我认为你应该将DialogClass作为mainActivity的内部类,然后只需调用runOnUiThread

希望这可以帮到你

答案 1 :(得分:0)

最后问题是我从一个不是ui线程的线程调用showDialog()。

我在阅读android dev blog on memory leaking时发现了这个问题,并意识到我已经将活动的句柄传递到应该超出的范围。

我现在从主要活动的runOnUiThread中调用showDialog(),因为sonu指出并且一切似乎都在工作。