从子线程AsyncTask更新UI主线程

时间:2012-02-17 18:04:14

标签: android multithreading user-interface

我是Android的新手,并且很难为gui工作获得简单的更新。

从我的主类我调用AsyncTask:

RepeatTimerTask task = new RepeatTimerTask(text, timerDummy);
task.execute(null);

异步类如下

class RepeatTimerTask extends AsyncTask<Void, String, Void> {
private long startTime;
private TextView txtToUpdate;
private Handler mHandler = new Handler();
long mStartTime = 0;
RepeatTimer timer;
long timerLength = 0;

public RepeatTimerTask(TextView txtToUpdate, RepeatTimer timer) {
    this.txtToUpdate = txtToUpdate;
    this.timer = timer;
    startTime = new Date().getTime();
    this.timerLength = timer.getTime() * 1000;
}




protected void onProgressUpdate(String newText) {
    try
    {

      txtToUpdate.setText(newText);
      txtToUpdate.invalidate();
    }catch (Exception e) {
        HErrorHandler.log(e);
    }
}

protected void onPostExecute() {
    txtToUpdate.setText("ALAAAAAMMMM");
}

@Override
protected Void doInBackground(Void... params) { 

    while (true) {
        try {
            synchronized (this) {
                this.wait(100);
            }
        } catch (InterruptedException e) {
            HErrorHandler.log(e);
            break;
        }

        long millis = System.currentTimeMillis() - startTime;
        if (millis <= 0
                || System.currentTimeMillis() > timerLength + startTime) {
            break;
        }
        int seconds = (int) (millis / 1000);
        int minutes = seconds / 60;
        seconds = seconds % 60;

        // !!!!!!!!!!!!!!!!!!   HERE THE ERROR1 OCCOURS!!!!!!!
        //txtToUpdate.setText(String.format("%d:%02d", minutes, seconds));
        //txtToUpdate.invalidate();
        String labelText = String.format("%d:%02d", minutes, seconds);
        publishProgress(labelText);
    }
    return null;
}


}

当我尝试更新TextView时出现错误:

    02-08 06:19:01.857: W/System.err(5625): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
    02-08 06:19:01.887: W/System.err(5625):     at android.view.ViewRoot.checkThread(ViewRoot.java:2932)
    02-08 06:19:01.897: W/System.err(5625):     at android.view.ViewRoot.requestLayout(ViewRoot.java:629)
    02-08 06:19:01.917: W/System.err(5625):     at android.view.View.requestLayout(View.java:8267)
    02-08 06:19:01.927: W/System.err(5625):     at android.view.View.requestLayout(View.java:8267)
    02-08 06:19:01.947: W/System.err(5625):     at android.view.View.requestLayout(View.java:8267)
    02-08 06:19:01.957: W/System.err(5625):     at android.view.View.requestLayout(View.java:8267)
    02-08 06:19:01.977: W/System.err(5625):     at android.widget.AbsListView.requestLayout(AbsListView.java:1102)
    02-08 06:19:01.997: W/System.err(5625):     at android.view.View.requestLayout(View.java:8267)
    02-08 06:19:02.007: W/System.err(5625):     at android.view.View.requestLayout(View.java:8267)
    02-08 06:19:02.030: W/System.err(5625):     at android.widget.TableLayout.requestLayout(TableLayout.java:226)
    02-08 06:19:02.037: W/System.err(5625):     at android.view.View.requestLayout(View.java:8267)
    02-08 06:19:02.057: W/System.err(5625):     at android.view.View.requestLayout(View.java:8267)
    02-08 06:19:02.068: W/System.err(5625):     at android.widget.TextView.checkForRelayout(TextView.java:5521)
    02-08 06:19:02.087: W/System.err(5625):     at android.widget.TextView.setText(TextView.java:2724)
    02-08 06:19:02.097: W/System.err(5625):     at android.widget.TextView.setText(TextView.java:2592)
    02-08 06:19:02.107: W/System.err(5625):     at android.widget.TextView.setText(TextView.java:2567)
    02-08 06:19:02.127: W/System.err(5625):     at com.hdit.RepeatTimerTask.doInBackground(RepeatTimerTask.java:74)
    02-08 06:19:02.147: W/System.err(5625):     at com.hdit.RepeatTimerTask.doInBackground(RepeatTimerTask.java:1)
    02-08 06:19:02.159: W/System.err(5625):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
    02-08 06:19:02.177: W/System.err(5625):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
    02-08 06:19:02.187: W/System.err(5625):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    02-08 06:19:02.207: W/System.err(5625):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
    02-08 06:19:02.217: W/System.err(5625):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
    02-08 06:19:02.237: W/System.err(5625):     at java.lang.Thread.run(Thread.java:1019)

我该怎么做才能避免这种情况?

不幸的是

  

onProgressUpdate

永远不会到达。

谢谢

3 个答案:

答案 0 :(得分:1)

您的问题来自您注释掉的代码。您无法更新主线程之外的视图。您正在使Task中的textview无效(它在自己的视图中运行)。要解决此问题,您需要刷新onProgressUpdate中的textview - 而不是soInBackground。

答案 1 :(得分:1)

解决方案是正确覆盖onProgressUpdate:

@Override
protected void onProgressUpdate(String... values)

非常感谢。

答案 2 :(得分:0)

AsyncTask中有4个部分。您可以从doInBackground格式以外的任何部分更新视图。从那里删除publishProgress(labelText);,您将会看到onProgressUpdate

在这里查看http://developer.android.com/reference/android/os/AsyncTask.html

相关问题