Android 许多异步任务生成时的异步任务性能问题。

Android 许多异步任务生成时的异步任务性能问题。,android,listview,android-asynctask,lazy-loading,Android,Listview,Android Asynctask,Lazy Loading,我正在尝试为列表视图的设备和web上的图像创建一个惰性图像加载程序。 我正在考虑使用什么以及如何使用一个线程来汇集我的请求(总是在运行,我可以附加一个视图和一个适配器,它将为我处理图像加载),缓存我已经加载的图像,并在加载之前检查图像的可见性,这样我就不会做不必要的工作 我有另一个想法,使用AsyncTask,就像论坛上许多人建议的那样。不过有一个缺点。我看到很多人使用newmytask().execute(URL)如果我想开始加载和停止按需加载图像,这会出现问题。 如果我使用每个映像的异步任务

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

我有另一个想法,使用
AsyncTask
,就像论坛上许多人建议的那样。不过有一个缺点。我看到很多人使用
newmytask().execute(URL)如果我想开始加载和停止按需加载图像,这会出现问题。
如果我使用每个映像的异步任务,那么我需要为每个映像创建新的异步任务,这是一个非常“新”的任务,我可以使用一个池,但是如果有太多的异步任务被卡住,我仍然会创建大约150-200个asyc任务,太多太多了,太多了

你们觉得怎么样?我认为线程在这里会做得更好:

  • 一直跑到死
  • 尝试从队列中获取作业,如果不是作业,请稍候
  • 如果作业可用,则获取它并开始处理
  • 每个请求都单独、连续地处理,并阻塞线程
  • Once does继续使用“2”
  • 适配器对需要显示的视图使用
    startLoadingImage()
    进行的每个排队将创建一个新作业,并在等待锁上调用notify
  • 如果我需要几个并行的GET\POST请求,我可以使用一个线程池来优化这段代码。
    此外,我正在缓存已下载\加载的图像,以便下次访问时快速加载。我们的想法是尽量减少GC和列表滞后。

    我认为您正在进行过早的优化。只要以最快的方式实现您所需要的,您就可以在以后改进实现。还有,为什么您需要同时启动200个异步任务?我不认为您将在一个屏幕上显示所有图像(在ListView的情况下,为什么要加载所有图像,即使用户永远无法滚动到列表的末尾?)

    我实现了如下内容:

    /** 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());
             }
         }
    }
    
    这甚至允许您使用
    mPendingThumbnailRequests.remove()取消请求

    全面实施如下:

    否,这是用户可以滚动到最后的点,所有图像都将预加载一个默认图像,如“等待加载”等,一旦加载图像,视图将得到通知,并且图像将放置在正确的视图中。一旦它被缓存,加载的响应时间就很快,所以不需要以异步方式进行。关于200个异步任务,这只是我为什么不使用它的一个例子……我这样做了,现在我得到了java.util.concurrent.RejectedExecutionException,如果我滚动太快,并且在正常滚动时任务的完成顺序混乱。这可能是最容易做到的。首先,这个代码绝对是好的,但是如果我考虑一个图像列表,这些图片以未知的速度和批次加载(因为用户可以按他喜欢的快或慢的速度滚动)。你会创建相对较多的AyncTasks,而你自己的线程只创建一次,然后一直休眠到你将一个新对象加入队列为止。的确,对他来说,内存会多一点,但如果你使用自己的池,避免在运行中创建新对象,那么它与GC相反是多余的()当我们重用现有的异步任务(如果有的话)时,不会创建很多异步任务。实际上,当用户开始滚动并且有一些缩略图需要检索时,它会重新创建一个新的缩略图。。。但这只是滚动开始时的一个分配问题。我从来都不喜欢休眠线程,更担心那些线程永远不会停止或被复制。嘿,我刚刚发现你是对的,我为每个Uri创建了一个新的AsyncTask。。。我会努力的。谢谢你给我看这个您不需要同步访问
    mPendingThumbnailRequests
    ?否则,某些异步任务可能会执行两次(或零次,具体取决于设置了
    AsyncTask.Status.FINISHED
    )。
    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());
        }
    }