使用Glide时出现的Android内存泄漏问题

10

我有一个活动,使用Glide在ImageView中加载图片。这是我的Glide代码示例:

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

我需要加载1到35张图片,每张图片的大小应在150ko到250ko之间。我无法缩小它。
该活动可以从主活动中多次访问,并且每次它会加载不同的图片。例如,第一次将是华盛顿的图片,然后是伦敦等其他城市的图片。
我的问题是,每次启动加载图片的活动时,内存使用量都会大幅增加: enter image description here 我可以启动3到5次活动,然后应用程序崩溃。错误消息为:
java.lang.OutOfMemoryError: Failed to allocate a 1411340 byte allocation with 1126320 free bytes and 1099KB until OOM

我读到了有关内存泄漏的文章,但我认为Glide应该避免这个问题。我的图片活动在另一个活动开始之前就已经完成了,但是我的应用程序分配的内存似乎并没有减少。 我还在清单中的图片活动中添加了android:noHistory="true",但它并没有改变任何东西。
我在清单中添加了android:largeHeap="true",但这只是推迟了我的问题(我可以启动大约10到15次图片活动),在我的ImageViews中有很多图片没有加载,然后应用程序崩溃,所以这对我来说不是一个好的解决方案。
我也试图在使用Glide时添加.skipMemoryCache(true),但我没有注意到任何变化。
我想每次从图片活动返回主活动时,“内存使用”应该减少,然后当我再次启动我的图片活动时,随着新图片的增加而增加。但是从蓝色图表上看,它几乎只增加。你能看出我该怎么做吗?

每次按返回键时,您是否完成了活动? - Divyesh Patel
你是否尝试从Activity上下文而非image上下文中调用Glide?我猜测是因为Glide在某种程度上持有对该图像的引用,所以不能进行垃圾回收。请将 Glide.with(ImageVOne.getContext()) 更改为 Glide.with(this)(this指代ActivityB)。 - NSimon
@Alex9494 你可以检查一下我的答案,可能会有帮助。 - tahsinRupam
我认为你可能在某个地方泄漏了上下文,你的活动中是否使用了任何静态字段? - Andrej Jurkin
谢谢大家,你们的答案帮了我很多!我将Glide.with(ImageViewOne.getContext())更改为Glide.with(this),解决了监听器的问题,现在我可以看到我的内存图上下波动而不仅仅是上升 :) 我的分配内存约为200mb,您认为这太高了吗? - Alex9494
2个回答

15
您可以采取几种措施来防止出现内存溢出错误。具体如下:
  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);
    

您可以在此处查看Glide的缓存机制


嗯,这看起来确实很像对这个答案的篡改版本:https://dev59.com/bGkw5IYBdhLWcg3wBV3j#43713485 - Sakiboy
1
别过于高估自己了。我曾经遇到过类似的问题,并尝试了不同的解决方案。因此,我试图在一个答案中呈现所有的解决方案。我没有时间看一个仅在一周前发布的答案。此外,有很多更好的答案可供选择,为什么要费心呢? - tahsinRupam
5
随着Glide 4.x的出现,这已不再是最佳解决方案。 Glide.get(context).clearMemory(); 清除所有内存并不是特别高效的做法,应尽可能避免,以避免出现卡顿和加载时间增加的情况。 http://bumptech.github.io/glide/doc/caching.html#memory-cache - SjoerdvGestel
想象一下在RecyclerView中使用Glide并放置.skipMemoryCache(true) - Farid

-1

使用Glide不会导致内存泄漏的问题,您可能会保留一些其他活动的引用,例如监听器或者在启动活动时忘记注销已注册的内容,这将导致整个活动无法进行垃圾回收。

因此,每次启动活动或片段时,都会创建新实例,而旧实例也会因为任何未注销的罪犯实例而保留在内存中。

使用Eclipse MAT查找您的泄漏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接