我在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.
如何解决此错误?
答案 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();
}