【问题标题】:Replacing images in custom adapter - AsyncTask / multiple threads替换自定义适配器中的图像 - AsyncTask / 多线程
【发布时间】:2014-04-15 13:30:10
【问题描述】:

我有一个AsyncTask,它加载文件和文件夹列表并使用我的自定义适配器将它们放在我的自定义列表视图中。

这个自定义 Listview 有一个 ImageView 和一个 TextView。

最初加载列表时,我为每个文件和文件夹加载一个“虚拟”图像(我只使用一个可绘制对象)。我这样做是为了快速加载列表。

第一个异步任务完成后,我想用真实图像缩略图(来自 Dropbox)替换任何虚拟可绘制图像。

所以 - 要完成这部分,我只需启动另一个 AsyncTask 即可。它一个一个地加载每个缩略图,并将适配器中的默认虚拟图像替换为真实图像。

我使用 onProgressUpdate 刷新适配器,以便在下载每个缩略图后更新 ListView。它似乎工作正常,图像已下载、替换,并且用户仍然可以在图像更新时滚动。

问题: 它相当慢。检索单个缩略图并加载它需要 1-2 秒。

问题:

  1. 有没有办法让多个线程下载 缩略图,以便它们分批加载,例如一次10个?无需冻结 UI!

  2. 我看到的问题是知道将适配器放在哪里 下载后的缩略图(请参阅我的代码以了解我如何 目前使用 int 计数器执行此操作)。

这是我的 AsyncTask,用于获取真实缩略图和替换虚拟图像。它一次从 Dropbox 下载一个图像。如果我可以在多个线程中执行此操作,那就太好了!

 private class loadActualThumbs extends AsyncTask<DbxFileSystem, Integer, Boolean> {

        @Override
        protected  void onPreExecute()
        {

        }
        @Override
        protected Boolean  doInBackground(DbxFileSystem... params) {
            //Opens thumbnails for each image contained in the dropbox folder
            try {
                DbxFileSystem fileSystem = params[0];
                DbxFile file = null;
                int loopCount=0; //I use this to identify where in the adapter the real image should go

                for (DbxFileInfo fileInfo: fileSystem.listFolder(currentPath)) {

                    try{

                        if(fileInfo.thumbExists) // if it has a thumbnail then retrieve it
                        {
                            file = fileSystem.openThumbnail(fileInfo.path, ThumbSize.S, ThumbFormat.PNG);
                            Bitmap image = BitmapFactory.decodeStream(file.getReadStream());
                            pix.set(loopCount,image); //replace the default image with the real one
                            loopCount++;
                            publishProgress(1);
                        }
                        else
                        {
                            // its a folder so no image needed
                            loopCount++;//still need to increment this though

                        }
                    }
                    catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                    System.gc();
                }

                file.close(); //close the file outside of the loop

            }
            catch (Exception e) {
                e.printStackTrace();
                return false;
            } finally {

            }
            return true;
        }
        @Override
        protected void onProgressUpdate(Integer...progress) {

               //we want to load the image here to the adapter
            adapter.notifyDataSetChanged();
            super.onProgressUpdate(progress);
        }
        @Override
        protected void onPostExecute(Boolean result) {


        }
}

【问题讨论】:

  • 从进一步阅读中我可能可以像这样调用我的 AsyncTask,但我猜即使它确实有效,图像也可能会加载到适配器中的错误位置:thumbs.executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR,dbxFs);

标签: android android-listview android-asynctask


【解决方案1】:

看看Universal Image Loader。它会在后台加载您的所有图像,如果您愿意,可以缓存它们,您可以设置一次下载多少个(线程数)。

【讨论】:

  • 我看过这个,它不适合我的目的。主要是因为您需要使用 URL 来下载图像。如果您快速查看我的代码,您会发现我正在使用 Dropbox SDK,它不为您提供缩略图的 URL。获取缩略图的唯一方法是将Stream 解码为位图。
  • 啊我的错。没意识到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-28
  • 2015-05-02
  • 2017-07-16
相关资源
最近更新 更多