异步加载图像缩略图Android

时间:2014-07-31 12:45:57

标签: android listview android-asynctask

我有什么

我有一个AsyncTask来生成缩略图并将它们附加到ImageView。

public class ThumbnailTask extends AsyncTask<String, Void, Bitmap> {

    private final WeakReference imageViewReference;

    public ThumbnailTask(ImageView imageView) {
        imageViewReference = new WeakReference(imageView);
    }

    @Override
    protected Bitmap doInBackground(String... params) {

        return decodeSampledBitmapFromFile(params[0], 115, 90);
    }

    protected void onPostExecute(Bitmap bitmap) {
        if (isCancelled()) {
            bitmap = null;
        }

        if (imageViewReference != null) {
            ImageView imageView = (ImageView) imageViewReference.get();
            if (imageView != null) {

                if (bitmap != null) {
                    imageView.setImageBitmap(bitmap);
                }
                else {
                    imageView.setImageDrawable(imageView.getContext().getResources()
                            .getDrawable(R.drawable.thumb3));
                }
            }

        }
    }

}

现在我调用这样的执行方法,

if(holder.fileImage != null){
                    new ThumbnailTask(holder.fileImage).execute(o.getFilePath());
                }

我的问题

我遇到的主要问题是,当我向下滚动列表时,错误的缩略图会附加到图像视图中。需要一些时间才能将正确的图像再次附加到缩略图上。

任何人都可以帮我解决这个问题,以便将正确的缩略图附加到正确的项目上吗?

2 个答案:

答案 0 :(得分:0)

最重要的是要记住ListView使用的布局是否被回收。虽然我不知道您的确切实施情况,但我冒昧地猜测问题是:

  1. 首先,您ThumbnailTask[img1]与特定ImageView
  2. 相关联
  3. 滚动列表,因此ThumbnailTask[img11]现在也可能与ImageView ThumbnailTask[img1]相关联,但没有ThumbnailTask[img1]的知识。
  4. ImageView完成后,它会更新ThumbnailTask[img11]
  5. 一段时间ImageView完成并更新相同的{{1}}。
  6. 正确地异步加载和显示内容是一个非常重要的问题,我建议您尝试使用以下任何一个库来完成它:

    1. Android-Universal-Image-Loader
    2. picasso
    3. ion

答案 1 :(得分:0)

有关如何在列表或网格中异步正确加载位图的详细讨论,请参阅http://developer.android.com/training/displaying-bitmaps/index.html,如果您不想使用第三方框架为您执行此操作(因为Kai提到过) ,它是一个非常重要的问题,以使其正确)。

来自链接:

public void loadBitmap(int resId, ImageView imageView) {
    if (cancelPotentialWork(resId, imageView)) {
        final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
        final AsyncDrawable asyncDrawable =
                new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);
        imageView.setImageDrawable(asyncDrawable);
        task.execute(resId);
    }
}

static class AsyncDrawable extends BitmapDrawable {
    private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;

    public AsyncDrawable(Resources res, Bitmap bitmap,
            BitmapWorkerTask bitmapWorkerTask) {
        super(res, bitmap);
        bitmapWorkerTaskReference =
            new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
    }

    public BitmapWorkerTask getBitmapWorkerTask() {
        return bitmapWorkerTaskReference.get();
    }
}

public static boolean cancelPotentialWork(int data, ImageView imageView) {
    final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);

    if (bitmapWorkerTask != null) {
        final int bitmapData = bitmapWorkerTask.data;
        if (bitmapData != data) {
            // Cancel previous task
            bitmapWorkerTask.cancel(true);
        } else {
            // The same work is already in progress
            return false;
        }
    }
    // No task associated with the ImageView, or an existing task was cancelled
    return true;
}

private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
   if (imageView != null) {
       final Drawable drawable = imageView.getDrawable();
       if (drawable instanceof AsyncDrawable) {
           final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
           return asyncDrawable.getBitmapWorkerTask();
       }
    }
    return null;
}

您可能缺少的关键部分是在开始新任务之前取消之前的任务,这可以解释为什么先前的图像正在其中加载。