Recycler NetworkImageView Scrolling back and forwa

2019-08-26 09:12发布

I am working to add an image from the gallery horizontally using recycler view as follows. I could able to add images next to each other.

The following code works but crashes sometimes because of out of memory concerns.

RecyclerViewAdapter, I am calling setSelectedPic method to load the image.

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

ImageUtil Class

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());
        }
    }

And then I decide to resize the images to solve the aferomentioned issue, out of memory-.The following code works. BUT, when I scroll back to first image, that image shows blank or white, but when I delete the second image, then I could able to see first image. I could not able to figure out the root of the problem. I am using NetworkImageView.

RecyclerViewAdapter, I am calling setSelectedPic method to load the image.

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

ImageUtil Class

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条回答
迷人小祖宗
2楼-- · 2019-08-26 10:03

You should scale your Bitmap and use caching for reducing loading time. Here on this repository I've put reference code for approaching image loading with scaling and caching.

I report here code to be used for setPic method. This essentially uses an LruCache for improving Bitmap loading while scrolling. This could be a good starting point. Notice also that Bitmap are scaled before putting them in cache.

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);
}

I suggest also to refer to Android Developers documentation here (for efficient Bitmap loading) and here (for Bitmap caching with Volley).

查看更多
登录 后发表回答