产生许多AsyncTasks的AsyncTask性能问题。

时间:2010-09-19 09:30:39

标签: android listview android-asynctask lazy-loading

我正在尝试为设备和网络上的ListView图像创建一个懒惰的图像加载器。 我正在考虑使用什么以及如何使用,一方面我可以使用一个集合我的请求的线程(总是运行,我可以附加一个视图和一个适配器,它将为我处理图像加载),缓存我已经在加载之前加载图像并检查图像的可见性,这样我就不会做不需要的工作。

我还想到了在论坛中使用AsyncTask的许多建议。但有一个缺点。我看到许多使用new MyTask().execute(urls);如果我想开始加载并停止按需加载图像,这就会出现问题。 如果我对每个图像使用异步任务,那么我需要为每个图像创建新的异步任务,这需要很多“新”,我可以使用池,但如果太多的异步任务被卡住,我仍然会创建大约150- 200个asyc任务,对我来说太多了......

你们觉得怎么样?我认为一个主题在这里会做得更好:

  1. 继续奔跑直至被杀
  2. 尝试从队列中获取作业,如果不是作业,请等待。
  3. 如果某个职位可用,请获取并开始处理。
  4. 每个请求都是单独处理,串行处理并阻止该线程。
  5. 一旦继续'2'。
  6. 适配器使用startLoadingImage()为需要显示的视图执行的每个队列都将创建一个新作业并在等待锁上调用notify。
  7. 如果我想要并行使用多个GET \ POST请求,我可以使用线程池优化此代码。 此外,我正在缓存我已经下载的图像\加载以便在下次访问时快速加载。我们的想法是尽量减少GC并列出滞后。

2 个答案:

答案 0 :(得分:2)

我实现了这样的事情:

/** Contains all the pending requests for thumbnails. */
private LinkedList<Uri> mPendingThumbnailRequests = new LinkedList<Uri>();

private ThumbnailGetter mThmGetter = null;
/**
 * Asynchronous process for retrieving thumbnails from Uris.
 */
private class ThumbnailGetter extends AsyncTask<Uri, Integer, Uri> {
    private final String LOG_TAG = ThumbnailGetter.class
            .getSimpleName();
    /** The Uri beeing processed */
    private Uri mUri = null;
    /*
     * (non-Javadoc)
     * 
     * @see android.os.AsyncTask#doInBackground(Params[])
     */
    @Override
    protected Uri doInBackground(Uri... uris) {
        // We process Uris one after another... so the Array contains
        // only one Uri.
        mUri = uris[0];
        // Let the ThumbnailLoader do the job.
        Uri result = ItemsLoader.getThumbnail(mContext, mUri);
        return result;
    }
    /*
     * (non-Javadoc)
     * 
     * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
     */
    @Override
    protected void onPostExecute(Uri result) {
        super.onPostExecute(result);
        // Give the retrieved thumbnail to the adapter...
        mImageAdapter.updateThumbUri(mUri, result);
        // then process any other pending thumbnail request.
        if (!mPendingThumbnailRequests.isEmpty()) {
            mThmGetter = new ThumbnailGetter();
            mThmGetter.execute(mPendingThumbnailRequests.poll());
         }
     }
}

然后我使用以下方法添加Uris:

if (!mPendingThumbnailRequests.contains(imageUri)) {
    mPendingThumbnailRequests.offer(imageUri);
    if (mThmGetter == null
            || mThmGetter.getStatus() == AsyncTask.Status.FINISHED) {
        // If the previous instance of the thumbnail getter has
        // finished, start a new one.
        mHandler.sendEmptyMessage(MSG_SHOW_INDETERMINATE_PROGRESS);
        mThmGetter = new ThumbnailGetter();
        mThmGetter.execute(mPendingThumbnailRequests.poll());
    }
}

这甚至允许您使用mPendingThumbnailRequests.remove()

取消请求

完整的实施在这里: http://code.google.com/p/emailalbum/source/browse/EmailAlbumAndroid/trunk/src/com/kg/emailalbum/mobile/creator/SelectPictures.java

答案 1 :(得分:1)

我认为你正在做过早的优化。只需以最快的方式实现您的需求,您将始终可以改进实施。另外,为什么你需要同时启动200个AsyncTasks?我不认为你会在一个屏幕上显示所有图像(在ListView的情况下,为什么加载所有图像,即使用户永远不会滚动到列表的末尾?)。