即使使用ViewHolder / AsyncTask最佳实践,Android Gridview回收图像

时间:2016-06-16 23:35:59

标签: android gridview android-asynctask

以下代码中的gridview仍然不会在内存中保存图像,并在用户滚动后使用LRUCache加载它们。视图仍然可以回收。 我遵循最佳实践,例如使用Google Docs中的AsyncTask和ViewHolder。此外,在显示第一张图像之前,加载约400张高质量图片仍需要大约10秒钟。我该怎么做才能解决回收问题并加快高分辨率图像的加载速度?

public class CustomGridOfFilesEXIFDataAdapter extends ArrayAdapter<EXIFDataMarkerHolder> {

private LayoutInflater layoutInflater;
public int position;
private LruCache<String, Bitmap> mMemoryCache;
ArrayList<Uri> imageList;

//http://www.coderzheaven.com/2013/09/01/faster-loading-images-gridviews-listviews-android-menory-caching-complete-implemenation-sample-code/

public CustomGridOfFilesEXIFDataAdapter(Context context, ArrayList<EXIFDataMarkerHolder> listOfFiles) {
    super(context, 0, listOfFiles);
    layoutInflater = LayoutInflater.from(context);

    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = maxMemory / 8;

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {

        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in bytes rather than number
            // of items.
            return bitmap.getByteCount();
        }

    };
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    ViewHolderItems viewHolder;

    EXIFDataMarkerHolder fileExifData = getItem(position);

    if(convertView==null){

        convertView = layoutInflater.inflate(R.layout.maps_image_grid_single, null);
        viewHolder = new ViewHolderItems();
        viewHolder.vhImage = (ImageView) convertView.findViewById(R.id.img);
        viewHolder.vhImage.setScaleType(ImageView.ScaleType.CENTER_CROP);
        viewHolder.position = position;
        convertView.setTag(viewHolder);

    }else{
        viewHolder = (ViewHolderItems) convertView.getTag();
    }

    if (viewHolder.vhImage != null) {

        final String imageKey = fileExifData.filepath;
        final Bitmap bm = getBitmapFromMemCache(imageKey);
        if (bm == null) {
            if (cancelPotentialDownload(fileExifData.filepath, viewHolder.vhImage)) {
                ImageConfiguratorAsyncTask task = new ImageConfiguratorAsyncTask(viewHolder.vhImage);
                DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
                viewHolder.vhImage.setImageDrawable(downloadedDrawable);
                task.execute(fileExifData.filepath);
            }
        }
    }

    return convertView;
}

static class ViewHolderItems {
    ImageView vhImage;
    int position;
}

//region "Async File Retrieval"

class ImageConfiguratorAsyncTask extends AsyncTask<String, ViewHolderItems, Bitmap> {

    private String filepath;
    private final WeakReference<ImageView> imageViewReference;

    public ImageConfiguratorAsyncTask(ImageView imageView) {
        imageViewReference = new WeakReference<ImageView>(imageView);
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        Bitmap b = downloadBitmap(params[0]);
        addBitmapToMemoryCache(String.valueOf(params[0]), b);
        return b;
    }

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

        if (imageViewReference != null) {
            ImageView imageView = imageViewReference.get();
            ImageConfiguratorAsyncTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
            if (this == bitmapDownloaderTask) {
                imageView.setImageBitmap(bitmap);
            }
        }

    }

    private Bitmap downloadBitmap(String filepath) {

        try {
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(filepath, options);

            options.inSampleSize = ImageManipulation.calculateInSampleSize(options, 125, 125);

            options.inJustDecodeBounds = false;
            Bitmap scaledDownFile =  BitmapFactory.decodeFile(filepath, options);
            scaledDownFile = Bitmap.createScaledBitmap(scaledDownFile, 125, 125, true);
              //scaledDownFile = ImageManipulation.decodeBitmapFromFile(filepath, 50, 50);
            return scaledDownFile;

        } catch (Exception e) {

        } finally {

        }
        return null;
    }
}

static class DownloadedDrawable extends ColorDrawable {
    private final WeakReference<ImageConfiguratorAsyncTask> bitmapDownloaderTaskReference;

    public DownloadedDrawable(ImageConfiguratorAsyncTask bitmapDownloaderTask) {
        super(Color.WHITE);
        bitmapDownloaderTaskReference =
                new WeakReference<ImageConfiguratorAsyncTask>(bitmapDownloaderTask);
    }

    public ImageConfiguratorAsyncTask getBitmapDownloaderTask() {
        return bitmapDownloaderTaskReference.get();
    }
}

private static boolean cancelPotentialDownload(String url, ImageView imageView) {
    ImageConfiguratorAsyncTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

    if (bitmapDownloaderTask != null) {
        String bitmapUrl = bitmapDownloaderTask.filepath;
        if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
            bitmapDownloaderTask.cancel(true);
        } else {
            // The same URL is already being downloaded.
            return false;
        }
    }
    return true;
}

private static ImageConfiguratorAsyncTask getBitmapDownloaderTask(ImageView imageView) {
    if (imageView != null) {
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof DownloadedDrawable) {
            DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
            return downloadedDrawable.getBitmapDownloaderTask();
        }
    }
    return null;
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);
    }
}

public Bitmap getBitmapFromMemCache(String key) {
    return (Bitmap) mMemoryCache.get(key);
}

//endregion
}


public class ImageManipulation {

public static Bitmap decodeBitmapFromFile(String filepath, int reqWidth, int reqHeight) {

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(filepath, options);

    // Calculate inSampleSize
    options.inSampleSize = ImageManipulation.calculateInSampleSize(options, 20, 20);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    Bitmap scaledDownFile =  BitmapFactory.decodeFile(filepath, options);

    scaledDownFile = ImageManipulation.getResizedBitmap(scaledDownFile, 100);
    return scaledDownFile;
}

public static Bitmap getResizedBitmap(Bitmap image, int maxSize) {
    int width = image.getWidth();
    int height = image.getHeight();

    float bitmapRatio = (float)width / (float) height;
    if (bitmapRatio > 0) {
        width = maxSize;
        height = (int) (width / bitmapRatio);
    } else {
        height = maxSize;
        width = (int) (height * bitmapRatio);
    }
    return Bitmap.createScaledBitmap(image, width, height, true);
}

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}
}

0 个答案:

没有答案