10

I have an activity which loads pictures in ImageViews with glide. Here is a sample of my glide code:

    Glide.with(ImageVOne.getContext())
            .load(geoInfo.getPhotoUrl1())
            .skipMemoryCache(true)
            .priority(Priority.NORMAL)
            .into(ImageVOne);

I load from 1 to 35 pictures, each picture should be between 150ko & 250ko. I cannot reduce that.

This activity can be accessed several times in a session from the main activity, and each time it loads different pictures. For example the first time it will be pictures of Washington, then pictures of London etc.

My issue is that the use of memory increases a lot every time the activity that loads the pictures is started: enter image description here

I can start the activity from 3 to 5 times, then the app crashes. The error message is

java.lang.OutOfMemoryError: Failed to allocate a 1411340 byte allocation with 1126320 free bytes and 1099KB until OOM

I read posts about memory leaks but I thought Glide would avoid this issue. My activity with the pictures is finished before another one is started, but the memory allocated to my app do not seem to drop. I also added android:noHistory="true" to my picture activity in the Manifest but it doesn't change anything.

I added android:largeHeap="true" in my Manifest but it just postpone my issue (I can start the pictures activity about 10 to 15 times) and I get a lot of pictures not loaded in my imageviews before the app crashes, so its not a good solution for me.

I also tried to add .skipMemoryCache (true) when I use glide but I don't notice any change.

I guess my "memory use" should decrease every time I go from the pictures activity to the main activity, then increase when I start my pictures activity again with new pictures. But from what I see on the blue graph it almost only increases. Do you see what I should do?

Zoe
  • 27,060
  • 21
  • 118
  • 148
Alex9494
  • 1,588
  • 3
  • 12
  • 22
  • u finished activity every time back pressed? – Divyesh Patel Mar 08 '17 at 11:38
  • Did you try to invoke glide from the Activity context and not the image context? My best guess is, nothing can be GC'd as Glide holds a reference to the image somehow. Change Glide.with(ImageVOne.getContext()) to Glide.with(this) (this referring to ActivityB) – NSimon Mar 08 '17 at 11:38
  • @Alex9494 You may check my answer, it might be helpful. – tahsinRupam Mar 08 '17 at 12:16
  • I think you may be leaking a context somewhere, are you using any static fields in your activity? – Andrej Jurkin Mar 08 '17 at 12:59
  • Thank you everyone, your answers help me a lot ! I changed Glide.with(ImageVOne.getContext()) to Glide.with(this) and solved a problem with a listener, now I can see my memory graph going up and down, not only up :) My allocated memory is around 200mb, do you consider it as too high ? – Alex9494 Mar 08 '17 at 13:30

2 Answers2

15

You can take several measures to prevent getting Out of Memory Error. They are as follows.

  1. Using GridView/RecycleView to show images. Because they load only what they show. Suppose you have 50 images and 10 images are visible to your screen, it will load only 10. This will ease the pressure from your memory.

  2. Use PLACEHOLDER to load image instead of black-space. You can use low resolution image in drawable as placeholder.

  3. Use THUMBNAILS instead of actual images.

  4. You may use fixed dp for height and width of imageView.

  5. Set skipMemoryCache to true.

  6. CLEAR GLIDE memory onDestroy();

    @Override public void onDestroy() {
        super.onDestroy();
        Glide.get(this).clearMemory();
    }
    
  7. Override to smaller-size :

     .override(500, 600) //as example
    

    Here is a refined code for using GLIDE:

       Glide.with(this)
            .load(url)
            .thumbnail(0.5f)
            .skipMemoryCache(true) 
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(R.drawable.your_placeHolder)
            .into(imageVOne);
    

You may look at catching mechanism of Glide here.

tahsinRupam
  • 6,325
  • 1
  • 18
  • 34
  • Hmmm this sure does look a lot like the bastardized version of this answer: https://stackoverflow.com/a/43713485/2371425 – Sakiboy Jun 26 '17 at 09:20
  • 1
    Oh common! Don't overrate yourself. I faced similar kind of problem and tried different kinds of solutions. So I tried to present all the solutions in a single answer. Didn't have the time to look at an answer which was posted just a week before. Moreover, there are lots of better answers available than that so why bother? – tahsinRupam Jul 02 '17 at 06:55
  • 5
    with glide 4.x its not the best solution anymore Glide.get(context).clearMemory(); Clearing all memory isn’t particularly efficient and should be avoided whenever possible to avoid jank and increased loading times. http://bumptech.github.io/glide/doc/caching.html#memory-cache – SjoerdvGestel Sep 21 '17 at 14:24
  • Imagine using Glide in RecyclerView and putting this `.skipMemoryCache(true)` – Farid Aug 04 '22 at 13:00
-1

Using Glide would not be the issue of memory leak, you might keep some other reference of your activity like listener or you forgot to unregister something that have been registered while starting the activity which will results your whole activity cant get Garbage collected.

So every time you starting your activity or fragment it will create new instance while the old instance also keep in memory because of any unregistered culprit Instance.

use Eclipse MAT to find your leak.

Jagan
  • 590
  • 1
  • 8
  • 21