【问题标题】:Android memory leak with Glide使用 Glide 的 Android 内存泄漏
【发布时间】:2017-03-08 11:34:01
【问题描述】:

我有一个活动,可以在 ImageViews 中通过滑行加载图片。这是我的滑行代码示例:

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

我加载了 1 到 35 张图片,每张图片应该在 150ko 和 250ko 之间。我不能减少它。

这个活动可以在一个会话中从主活动多次访问,每次它加载不同的图片。例如,第一次是华盛顿的照片,然后是伦敦的照片等。

我的问题是每次启动加载图片的活动时,内存的使用都会增加很多:

我可以启动 3 到 5 次活动,然后应用程序崩溃。错误信息是

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

我阅读了posts about memory leaks,但我认为 Glide 会避免这个问题。我的图片活动在另一个活动开始之前完成,但分配给我的应用程序的内存似乎没有下降。 我还在清单中的图片活动中添加了android:noHistory="true",但它并没有改变任何东西。

我在我的清单中添加了android:largeHeap="true",但它只是推迟了我的问题(我可以启动图片活动大约 10 到 15 次)并且在应用程序崩溃之前我的图像视图中没有加载很多图片,所以它不是对我来说是一个很好的解决方案。

我也尝试在使用 glide 时添加 .skipMemoryCache (true),但我没有注意到任何变化。

我猜每次我从图片活动转到主要活动时我的“内存使用”应该会减少,然后当我用新图片再次开始我的图片活动时会增加。但从我在蓝色图表上看到的情况来看,它几乎只会增加。你知道我应该怎么做吗?

【问题讨论】:

  • 你每次回按都完成了活动?
  • 您是否尝试从 Activity 上下文而不是图像上下文调用 glide?我最好的猜测是,因为 Glide 以某种方式持有对图像的引用,所以没有任何东西可以被 GC 处理。将 Glide.with(ImageVOne.getContext()) 改为 Glide.with(this) (this指的是ActivityB)
  • @Alex9494 你可以看看我的回答,可能会有帮助。
  • 我认为您可能在某处泄漏了上下文,您是否在活动中使用了任何静态字段?
  • 谢谢大家,你们的回答对我帮助很大!我将 Glide.with(ImageVOne.getContext()) 更改为 Glide.with(this) 并解决了一个监听器的问题,现在我可以看到我的内存图上下波动,而不仅仅是上升 :) 我分配的内存约为 200mb ,你觉得太高了吗?

标签: android memory-leaks android-glide


【解决方案1】:

您可以采取多种措施来防止出现内存不足错误。它们如下。

  1. 使用 GridView/RecycleView 显示图像。因为他们只加载他们显示的内容。假设您有 50 张图片,并且屏幕上可以看到 10 张图片,它只会加载 10 张。这将减轻您的记忆压力。

  2. 使用 PLACEHOLDER 加载图像而不是黑色空间。您可以在drawable中使用低分辨率图像作为占位符。

  3. 使用 THUMBNAILS 代替实际图像。

  4. 您可以使用固定 dp 作为 imageView 的高度和宽度。

  5. 将 skipMemoryCache 设置为 true。

  6. CLEAR GLIDE 内存 onDestroy();

    @Override public void onDestroy() {
        super.onDestroy();
        Glide.get(this).clearMemory();
    }
    
  7. 覆盖到更小的尺寸:

     .override(500, 600) //as example
    

    这是使用 GLIDE 的精炼代码:

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

你可以看看Glide的捕捉机制here

【讨论】:

  • 嗯,这确实看起来很像这个答案的混蛋版本:stackoverflow.com/a/43713485/2371425
  • 哦,很常见!不要高估自己。我遇到了类似的问题并尝试了不同的解决方案。所以我试图在一个答案中提出所有的解决方案。没有时间查看一周前发布的答案。此外,还有很多比这更好的答案,那何必呢?
  • 使用 glide 4.x 它不再是最好的解决方案 Glide.get(context).clearMemory();清除所有内存并不是特别有效,应尽可能避免,以避免卡顿和增加加载时间。 bumptech.github.io/glide/doc/caching.html#memory-cache
【解决方案2】:

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

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

使用 Eclipse MAT 查找您的漏洞。

【讨论】:

    猜你喜欢
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    • 2014-08-05
    • 2015-07-20
    • 2013-08-23
    • 2020-08-15
    相关资源
    最近更新 更多