Recycler NetworkImageView向前和向后滚动,内存不足和调整大小问题

时间:2016-02-18 22:30:32

标签: android image android-recyclerview android-volley

我正在使用Recycler视图水平添加图库中的图像,如下所示。我能够将图像彼此相邻添加。

以下代码有效,但有时会由于内存不足而崩溃。

RecyclerViewAdapter ,我正在调用setSelectedPic方法加载图片。

@Override
public void onBindViewHolder(final ListViewHolder holder, int position) {
    PostProductImageLIst item = mItems.get(position);
    ImageUtil.setSelectedPic(holder.imgViewIcon, item.getPath());
}

ImageUtil类

public static void setSelectedPic(CustomNetworkImageView view, String url) {
        Context context = view.getContext();
        ImageLoader imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
        if (!TextUtils.isEmpty(url)) {
            if (url.startsWith("http")) {
                imageLoader.get(url, ImageLoader.getImageListener(view,
                        R.drawable.image, android.R.drawable
                                .ic_dialog_alert));
                view.setImageUrl(url, imageLoader);
            } else {
                try {
                    Uri uri = Uri.parse(url);
                    InputStream is = context.getContentResolver().openInputStream(uri);
                    Bitmap bitmap = BitmapFactory.decodeStream(is);
                    view.setLocalImageBitmap(bitmap);
                    if (is!=null) {
                        is.close();
                    }
                } catch (Exception ex) {
                    Log.e("Image", ex.getMessage(), ex);
                }
            }
        } else {
            view.setImageUrl("", CustomVolleyRequest.getInstance(view.getContext()).getImageLoader());
        }
    }

然后我决定调整图像大小以解决已经过时的问题,内存不足。以下代码可行。但是,当我滚动回第一张图像时,该图像显示为空白或白色,但是当我删除第二张图像时,我能够看到第一张图像。我无法找出问题的根源。我正在使用NetworkImageView。

RecyclerViewAdapter ,我正在调用setSelectedPic方法加载图片。

@Override
public void onBindViewHolder(final ListViewHolder holder, int position) {
    PostProductImageLIst item = mItems.get(position);
    ImageUtil.setSelectedPic(holder.imgViewIcon, item.getPath());
}

ImageUtil类

public static void setSelectedPic(CustomNetworkImageView view, String url) {
        Context context = view.getContext();
        ImageLoader imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
        if (!TextUtils.isEmpty(url)) {
            if (url.startsWith("http")) {
                imageLoader.get(url, ImageLoader.getImageListener(view,
                        R.drawable.image, android.R.drawable
                                .ic_dialog_alert));
                view.setImageUrl(url, imageLoader);
            } else {
                try {
                int targetW = view.getWidth();
                int targetH = view.getHeight();
                Uri uri = Uri.parse(url);
                InputStream is = context.getContentResolver().openInputStream(uri);
                BitmapFactory.Options bmOptions = new BitmapFactory.Options();
                bmOptions.inJustDecodeBounds = true;

                BitmapFactory.decodeFile(url, bmOptions);
                int photoW = bmOptions.outWidth;
                int photoH = bmOptions.outHeight;

                // Determine how much to scale down the image
                int scaleFactor = Math.min(photoW / targetW, photoH / targetH);
                // Decode the image file into a Bitmap sized to fill the View
                bmOptions.inJustDecodeBounds = false;
                bmOptions.inSampleSize = scaleFactor;
                Bitmap bitmap = BitmapFactory.decodeStream(is);
                Matrix matrix = new Matrix();
                matrix.postRotate(getImageOrientation(url));
                Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), matrix, true);
                view.setLocalImageBitmap(rotatedBitmap);
                if (is!=null) {
                    is.close();
                } catch (Exception ex) {
                    Log.e("Image", ex.getMessage(), ex);
                }
            }
        } else {
            view.setImageUrl("", CustomVolleyRequest.getInstance(view.getContext()).getImageLoader());
        }
    }

1 个答案:

答案 0 :(得分:2)

您应该缩放位图并使用缓存来减少加载时间。 Here在此存储库中我已经为使用缩放和缓存接近图像加载提供了参考代码。

我在这里报告用于setPic方法的代码。这实际上使用LruCache来改进滚动时的位图加载。这可能是一个很好的起点。另请注意,Bitmap在将它们放入缓存之前会进行缩放。

private static final int WIDTH = 100;

private LruCache<String, Bitmap> mMemoryCache;

public void setPic(MyImageView view, String url) {
    Context context = view.getContext();
    if (!TextUtils.isEmpty(url)) {
        if (url.startsWith("http")) {
            view.setImageUrl(url, VolleyHandler.getInstance(context).getImageLoader());
        } else {
            try {
                Uri uri = Uri.parse(url);
                Bitmap bitmap = mMemoryCache.get(url);
                if (bitmap == null) {
                    InputStream is = context.getContentResolver().openInputStream(uri);
                    bitmap = BitmapFactory.decodeStream(is);
                    Bitmap scaled = ImageUtils.getInstance().scaleBitmap(bitmap);
                    mMemoryCache.put(url, scaled);
                    if (is!=null) {
                        is.close();
                    }
                }
                view.setLocalImageBitmap(bitmap);
            } catch (Exception ex) {
                Log.e("Image", ex.getMessage(), ex);
            }
        }
    } else {
        view.setImageUrl("", VolleyHandler.getInstance(view.getContext()).getImageLoader());
    }
}

public Bitmap scaleBitmap(Bitmap bitmap) {
    int width = WIDTH;
    int height = (WIDTH * bitmap.getHeight()) / bitmap.getWidth();
    return Bitmap.createScaledBitmap(bitmap, width, height, false);
}

我建议也参考Android开发者文档here(用于高效的位图加载)和here(用于使用Volley进行位图缓存)。