user3274323
user3274323

Reputation:

android.view.ViewRootImpl$CalledFromWrongThreadException

i've showed progess bar in listview for download percentage of webpage.

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();
        }
    }

but when i notify the adapter i got below error.

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.

how to resolve this error?

Upvotes: 1

Views: 1191

Answers (4)

RVG
RVG

Reputation: 3576

change AsyncTask<String, Integer, String>instead ofAsyncTask<String, Void, String>

and

change

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

instead of

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

Upvotes: 0

PaF
PaF

Reputation: 3477

You shouldn't be overriding publishProgress() - you should be overriding onProgressUpdate(), which receives its data from publishProgress() but runs on the UI thread.

Do note though that currently your AsyncTask is not correctly defined. Your input and output are indeed both String, but your progress updates are Integer, which means you should be extending AsyncTask<String, Integer, String>.

Upvotes: 1

Yakiv Mospan
Yakiv Mospan

Reputation: 8224

You can not change UI on Background thread. Try to use onProgressUpdate(Object... values) AsyncTask method, it triggers on UI thread.

@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
}

Your code should look like this :

  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();
        }

    }

Upvotes: 1

AndroidCoder
AndroidCoder

Reputation: 2735

We can only change UI From Main Thread usually called as UI thread. We can not change UI on Background thread. you should override onProgressUpdate(), which receives its data from publishProgress() but runs on the UI thread.

Upvotes: 0

Related Questions