android.view.ViewRootImpl $ CalledFromWrongThreadException

时间:2014-02-25 13:44:11

标签: android

我在listview中显示了网页下载百分比的progess栏。

for(int i=0;i< 5;i++)
        {
            new UploadTask(i).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "http://www.google.com");
        }

my UploadTask

public class UploadTask extends AsyncTask<String, Void, String>
    {
        int id;
        public UploadTask(int id) {
            this.id = id;
        }
        @Override
        protected String doInBackground(String... params) {
            try {
                return HttpUrlConnection.getContentFromUrl(params[0], listener);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return "";
            }
        }
        HttpListener listener = new HttpListener() {

            @Override
            public void processCompletion(int x) {
                publishProgress(x);
            }
        };
        public void publishProgress(Integer... ints) {
            progressLevelList.set(id, ints[0]);
            uploadAdapter.notifyDataSetChanged();
        }
    }

但是当我通知适配器时我得到了以下错误。

java.lang.RuntimeException: An error occured while executing doInBackground()

    Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

如何解决此错误?

4 个答案:

答案 0 :(得分:1)

你不应该覆盖publishProgress() - 你应该覆盖onProgressUpdate(),它从publishProgress()接收数据,但在UI线程上运行。

请注意,目前您的AsyncTask未正确定义。您的输入和输出确实都是String,但您的进度更新为Integer,这意味着您应该展开AsyncTask<String, Integer, String>

答案 1 :(得分:1)

您无法在后台线程上更改UI。尝试使用onProgressUpdate(Object... values) AsyncTask方法,它在UI线程上触发。

@Override
protected void onPreExecute() {
  super.onPreExecute();
  //do you bg work here

  publishProgress(null);

  //do you bg work here
}

@Override
protected void onProgressUpdate(Void... values) {
 super.onProgressUpdate(values);
 //update UI here
}

您的代码应如下所示:

  public class UploadTask extends AsyncTask<String, Integer, String>
    {
        int id;
        public UploadTask(int id) {
            this.id = id;
        }
        @Override
        protected String doInBackground(String... params) {
            try {
                return HttpUrlConnection.getContentFromUrl(params[0], listener);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return "";
            }
        }
        HttpListener listener = new HttpListener() {

            @Override
            public void processCompletion(int x) {
                publishProgress(x);
            }
        };

        @Override
        protected void onProgressUpdate(Integer... values) {
            progressLevelList.set(id, ints[0]);
            uploadAdapter.notifyDataSetChanged();
        }

    }

答案 2 :(得分:0)

我们只能在主线程中更改UI,通常称为UI线程。我们无法在后台线程上更改UI。你应该重写onProgressUpdate(),它从publishProgress()接收数据,但在UI线程上运行。

答案 3 :(得分:0)

更改AsyncTask<String, Integer, String>而不是AsyncTask<String, Void, String>

更改

@Override
    public void onProgressUpdate(Integer... ints) {
            progressLevelList.set(id, ints[0]);
            uploadAdapter.notifyDataSetChanged();
        }

而不是

public void publishProgress(Integer... ints) {
            progressLevelList.set(id, ints[0]);
            uploadAdapter.notifyDataSetChanged();
        }