Reputation:
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
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
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
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
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