Out Of Memory Error When loading more images in Glide

前端 未结 11 913
我寻月下人不归
我寻月下人不归 2020-12-31 06:32

Edited:

  • In my application, I am loading more than 300 images in home page. I used glide to load images. I\'m getting Out of
相关标签:
11条回答
  • 2020-12-31 06:55

    Probably a different approach can be taken to resolve this. To achieve this you can use a different ImageAdapter with

    Glide.with(mActivity).loadFromMediaStore(_imageInfo.getmUri())
    

    this does not crash being using MediaStoreThumbFetcher

    To have more control over the load do the following using Glide v4

    // usage:
    Glide.with(mActivity).load(_imageInfo)....
    
    // in GlideModule.registerComponents
    registry.prepend(ImageInfo.class, ImageInfo.class, new UnitModelLoader.Factory<ImageInfo>());
    registry.prepend(ImageInfo.class, Bitmap.class, new ImageInfoBitmapDecoder(context));
    
    class ImageInfoBitmapDecoder implements ResourceDecoder<ImageInfo, Bitmap> {
        private final ContentResolver contentResolver;
        private final BitmapPool pool;
        public ImageInfoBitmapDecoder(Context context) {
            this.contentResolver = context.getContentResolver();
            this.pool = Glide.get(context).getBitmapPool();
        }
        @Override public boolean handles(ImageInfo source, Options options) { return true; }
        @Override public @Nullable Resource<Bitmap> decode(ImageInfo source, int width, int height, Options options) {
            Bitmap thumb = Thumbnails.getThumbnail(contentResolver, source.getmId(), Thumbnails.MINI_KIND, null);
            return BitmapResource.obtain(thumb, pool);
        }
    }
    

    Using following API's we can figure out free memory left out and size of the bitmap

    You can check available memory and bitmap details (if needed) as a pre-check

    Check the amount of free memory left

    public static final float BYTES_IN_MB = 1024.0f * 1024.0f;
    
        public static float megabytesFree() {
            final Runtime rt = Runtime.getRuntime();
            final float bytesUsed = rt.totalMemory();
            final float mbUsed = bytesUsed/BYTES_IN_MB;
            final float mbFree = megabytesAvailable() - mbUsed;
            return mbFree;
        }
    
        public static float megabytesAvailable() {
            final Runtime rt = Runtime.getRuntime();
            final float bytesAvailable = rt.maxMemory();
            return bytesAvailable/BYTES_IN_MB;
    }
    

    Check how big is the bitmap we want to load

    private void readBitmapInfo() {
            final Resources res = getActivity().getResources();
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeResource(res, R.drawable.brasil, options);
            final float imageHeight = options.outHeight;
            final float imageWidth = options.outWidth;
            final String imageMimeType = options.outMimeType;
            Log.d(TAG, "w,h, type:"+imageWidth+", "+imageHeight+", "+imageMimeType);
            Log.d(TAG, "estimated memory required in MB: "+imageWidth * imageHeight * BYTES_PER_PX/MemUtils.BYTES_IN_MB);
    }
    

    For more details go through Java methods to check memory and bitmap and github discussion

    0 讨论(0)
  • 2020-12-31 06:56
    • I solved this issue by removing nested scroll view placed above recyclerview. Why OutOfMemory error occurred means, when loading more than 200 images in home page, it is loading all 200 images because of using nested scroll view above recyclerview.

    • So I can't check the logcat image view width and height one by one in adapter.

    • After removed nested scroll view fixed out of memory error.because it will load only 3 images displayed in device when coming to home activity.

    • Also check this, how to use scroll instead of nested scroll view.

    0 讨论(0)
  • 2020-12-31 06:56
    • your images should not be too large ( if they are, use .thumbnail(...f) )
    • use .skipMemoryCache(true) if you are not force to keep images in cache
    • you can use .diskCacheStrategy(DiskCacheStrategy.NONE) to deactivate the disk cache
    0 讨论(0)
  • 2020-12-31 06:57

    This is not an exact solution to your problem, but you need to keep these things in mind while loading images in a list using Glide.

    The main threatening part of your problem is the image size. The image you're getting is almost 1mb each! Which is in fact too large for displaying them into a list having 300+ items. So if you're doing the server side too, its always recommended to have the images in several different sizes.

    For example, in case of showing a friend list along with their profile pictures, I would suggest you get the whole list first from the server. Then fetch all of the profile images and store them locally. Then populate the ListView. And the most important part is while uploading a profile picture of an user to the server, after uploading it, the server needs to keep several sizes of it e.g. low, mid and high res version. So that while serving the profile picture urls for the ListView the server might provide the images with low res as they'll be used most likely for thumbnails.

    Using RecyclerView instead of ListView is a good call too. But it won't solve the problem you've here when you're in a low-end device.

    OMM has nothing to do with you can solve programatically. You need to resize your image to a lower res version.

    You can check for the Glide's caching mechanism too. I would suggest you use the caching strategy so that every time you don't have to load the image from server.

    Good luck.

    0 讨论(0)
  • 2020-12-31 06:59

    In order to prevent Out of Memory error one can just make precautions to make sure that it will not occurs. So the answer of this question is actually a bunch of suggestions one can suggest. So do I.

    As suggested by @Reaz Murshed I am also recommending to have the images in several different sizes. Apart from this I would like to add few more things that might help you analyze this issue and solve it.

    As far as I remember OOM was always a usage error, largeHeap will just delay it; or if it's a large load then maybe it's not possible. So I am suggesting you to follow this link to diagnose for memory leaks.

    Stack traces of OutOfMemoryErrors don't help at all for diagnosing them. It just tells you it's broken and something filled up the memory. This filling happens much before the actual exception was thrown. This also implies that usually whatever throws the OOM is not actually the culprit. The only exception to this is when the amount of wannabe allocated memory is simply too big, for example: an array to be allocated is bigger than the maximum memory, then you know that some calculation went really wrong, like a 32000x32000@4 image would take around 4GB of memory.

    If you can reproduce: get a heap dump and analyze your app's usage. Normal OOM diagnostic steps:

    • Reproduce exception (wait till you see it in LogCat)

    • Take a heap dump(To analyze memory leaks)

    • Analyze it for big objects and leaks

    In above shared link there is few another links regarding how to take heap dump? and issues that are identical with this one.

    So I suggest you to analyze for memory leaks and take necessary steps to prevent OOM.

    Hope this will help you.

    0 讨论(0)
提交回复
热议问题