6

我有一个 AsyncTask 更新 ActionBarSherlock 进度实现。尽管 onProgressUpdate 声称在 UI 线程上执行,但它以某种方式引发了线程错误。

protected void onProgressUpdate(Integer... values)
{
    setSupportProgress(values[0]);
}

错误是:

03-06 00:13:11.672: E/AndroidRuntime(4183): at com.anthonymandra.framework.GalleryActivity$ShareTask.onProgressUpdate(GalleryActivity.java:476)

只有创建视图层次结构的原始线程才能接触其视图。

据我所知,我应该为此访问 UI 线程...

我的应用程序中有许多正在工作的 AsyncTasks,但根据要求,这里是 doInBackground(简化版):

for (MediaObject image : toShare)
{
    BufferedInputStream imageData = image.getThumbStream();
    File swapFile = getSwapFile(...);
    write(swapFile, imageData);
    ++completed;
    float progress = (float) completed / toShare.size();
    int progressLocation = (int) Math.ceil(progressRange * progress);
    onProgressUpdate(progressLocation);
}
4

3 回答 3

4

好的,问题是当您应该调用 publishProgress 时,您正在调用 onProgressUpdate。OP自己想出了这个,所以我只是复制粘贴了它,所以他/她不需要等待接受答案。以下是 AsyncTasks 如何工作的信息,这是很好的知识。


你是AsyncTask在 UI 线程上创建的吗?如果你不是,那就是问题所在。onProgressUpdate将在创建AsyncTask.

更新:让我们有一些代码挖掘时间(API 15 源代码)!

protected final void publishProgress(Progress... values) {
    if (!isCancelled()) {
        sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
                new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    }
}

这家伙会称它为静态HandlersHandler。文档说:

当您创建一个新的处理程序时,它会绑定到创建它的线程的线程/消息队列——从那时起,它会将消息和可运行对象传递到该消息队列并在它们从消息中出来时执行它们队列。

感谢 Bruno Mateus 的文档查找技巧:

看,我在文档页面找到:线程规则 - 必须遵循一些线程规则才能使此类正常工作: - AsyncTask 类必须加载到 UI 线程上。这是从 JELLY_BEAN 自动完成的。- 任务实例必须在 UI 线程上创建。必须在 UI 线程上调用 execute(Params...)。- 不要手动调用 onPreExecute()、onPostExecute(Result)、doInBackground(Params...)、onProgressUpdate(Progress...)。- 任务只能执行一次(如果尝试第二次执行将抛出异常。)

于 2013-03-05T14:39:19.833 回答
1

您可以将 AsyncTask 声明为活动的内部类,如下所示:

public void onClick(View v) {
   new DownloadImageTask().execute("http://example.com/image.png");
}

 private class DownloadImageTask extends AsyncTask {
      protected Bitmap doInBackground(String... urls) {
          return loadImageFromNetwork(urls[0]);
     }

     protected void onPostExecute(Bitmap result) {
          mImageView.setImageBitmap(result);
     }
 }
于 2013-03-05T15:19:18.237 回答
1

我手动调用:

onProgressUpdate

你应该打电话

publishProgress

容易犯错,但信息很好。西蒙和布鲁诺值得称赞,如果您愿意,请发布答案。感谢您的快速和广泛的响应!

于 2013-03-05T15:38:36.173 回答