vinay
vinay

Reputation: 361

Out of Memory Error when downloading a large image from Glide

Here is the code in which I am trying to download a large image..

RequestOptions requestOptions = new RequestOptions();
            requestOptions.diskCacheStrategy(DiskCacheStrategy.ALL);
            requestOptions.skipMemoryCache(true);
Glide.with(this)
 .load(rogImage)
 .apply(requestOptions)
 .listener(new RequestListener<Drawable>() {
        @Override
        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
            return false;
        }

        @Override
        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
            ProgressBarHandler.unloadProgressScreen(getActivity());
            return false;
        }
    })
    .into(new SimpleTarget<Drawable>() {
        @Override
        public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
            tempImageView.setImageDrawable(resource)
        }

    });

I end up most of the time in onLoad failed method with OutOfMemoryError.

when I checked in the Device File Explorer the images is being downloaded but not loaded into image view second time, First time it works perfectly for large images.

I am repeating the same code for second time call.

Below is the actual error message given in android studio.

Glide: Root cause (1 of 13)
    java.lang.OutOfMemoryError: Failed to allocate a 210639956 byte allocation with 16777216 free bytes and 197MB until OOM
  at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
  at android.graphics.Bitmap.nativeCreate(Native Method)
  at android.graphics.Bitmap.createBitmap(Bitmap.java:975)
  at android.graphics.Bitmap.createBitmap(Bitmap.java:946)
  at android.graphics.Bitmap.createBitmap(Bitmap.java:913)
  at com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool.createBitmap(LruBitmapPool.java:149)
  at com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool.getDirty(LruBitmapPool.java:142)
  at com.bumptech.glide.load.resource.bitmap.Downsampler.setInBitmap(Downsampler.java:688)
  at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeFromWrappedStreams(Downsampler.java:297)
  at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:207)
  at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:160)
  at com.bumptech.glide.load.resource.bitmap.ByteBufferBitmapDecoder.decode(ByteBufferBitmapDecoder.java:33)
  at com.bumptech.glide.load.resource.bitmap.ByteBufferBitmapDecoder.decode(ByteBufferBitmapDecoder.java:16)
  at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:72)
  at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:55)
  at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:45)
  at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:58)
  at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:43)
  at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:498)
  at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:469)
  at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:455)
  at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:407)
  at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:376)
  at com.bumptech.glide.load.engine.DataCacheGenerator.onDataReady(DataCacheGenerator.java:95)
  at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:74)
  at com.bumptech.glide.load.engine.DataCacheGenerator.startNext(DataCacheGenerator.java:75)
  at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:299)
  at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:266)
  at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:230)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
  at java.lang.Thread.run(Thread.java:818)
  at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:446)

you can check out the screenshot which shows that images are been downloaded and stored in device.

enter image description here

Upvotes: 0

Views: 2856

Answers (4)

vinay
vinay

Reputation: 361

Its been a while since I posted this question after going through all the solution provided, I am posting a solution which worked for me.

First created an single instance of glide and used it across the application

mainFragment.getmGlide().with(mainFragment.getMcurrentContext())

Next added the Request options to restrict the height and width of the image which considerably reduced the memory usage.

RequestOptions requestOptions = new RequestOptions();
    requestOptions.dontAnimate();
    requestOptions.diskCacheStrategy(DiskCacheStrategy.RESOURCE);
    requestOptions.timeout(10000);
    requestOptions.override(2000,2000);
    requestOptions.fitCenter();
    requestOptions.format(DecodeFormat.PREFER_RGB_565);
mainFragment.getmGlide().with(mainFragment.getMcurrentContext())
 .asBitmap()
 .load(rogImage)
 .apply(requestOptions)
 .listener(new RequestListener<Drawable>() {
        @Override
        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
            return false;
        }

        @Override
        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
            ProgressBarHandler.unloadProgressScreen(getActivity());
            return false;
        }
    })
    .into(new SimpleTarget<Drawable>() {
        @Override
        public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
            tempImageView.setImageDrawable(resource)
        }

    });

Thanks all for your proposed solution.

Upvotes: 1

Amir Hossein Mirzaei
Amir Hossein Mirzaei

Reputation: 2375

210 mb image (o.O) is too large to loading it into memory ! if your image size is really 210 mb i think best why is to download the image from internet as stream to disk by using httpConnection or libraries like okhttp and than loading Scaled Down Version of your image into memory and showing it to user !

see the developers link for loading large bitmaps efficient :

https://developer.android.com/topic/performance/graphics/load-bitmap.html#load-bitmap

use this library if you want to show whole image to user :

https://github.com/davemorrissey/subsampling-scale-image-view

Upvotes: 1

Sabyasachi
Sabyasachi

Reputation: 3599

Try below

Glide.with(context)
    .load(imgUrl)
    .thumbnail(0.1f)
    .into(imageView);

Check Referrence

Upvotes: 2

Jyot
Jyot

Reputation: 540

Add this in manifest

  android:largeHeap="true"

Also Add this is app.gradle

 dexOptions {// Prevent OutOfMemory with MultiDex during the build phase
        javaMaxHeapSize "4g"
    }

Upvotes: 3

Related Questions