【问题标题】:Memory not freeing after fragment is removed删除片段后内存未释放
【发布时间】:2016-07-26 14:10:07
【问题描述】:

我有一个Fragment,其中有一个RecyclerView

在这个RecyclerView,我可能偶尔会下载并显示图片(加载了GlideImageView

所以当我打开Fragment 时,使用的内存有时可能会从 30MB 左右跳到 100MB 左右甚至更多。

在持有FragmentActivity 完成后,内存不会释放。和以前一样。

我检查了Glide 文档,显然我们不必担心在RecyclerView 中释放Bitmaps。这是一个很大的问题,因为应用程序经常因此而因 OOM 而崩溃。

Fragment 被删除时,我应该如何正确处理释放内存?

编辑:另一个观察结果

我注意到的另一件事是,如果我完成 Activity 然后再次启动相同的 Activity。内存会跳回一会儿,然后又回到 100MB,这让我相信在再次启动 Fragment 之前内存已被清除。

【问题讨论】:

    标签: android android-fragments android-glide android-memory


    【解决方案1】:

    垃圾收集有时是 Android 中的一个痛苦问题。 大多数开发者没有考虑到这个问题,只是在没有任何资源分配意识的情况下继续开发。

    这当然会导致内存问题,例如泄漏、OOM 和不必要的资源绑定。 绝对没有自动释放内存的方法。在任何情况下,您都不能完全依赖垃圾收集器

    当您通过 Fragment 或 Activity 的 onDestroy() 方法时,您可以而且应该做的是清除应用程序中不再需要的任何构造。您可以执行以下操作:

    1. 避免监听者的匿名实例。创建侦听器并在您不再需要它们时销毁它们。
    2. 将所有侦听器(无论是单击、长按等)设置为 null
    3. 清除所有变量、数组。对 Activity/Fragment 中包含的所有类和子类应用相同的过程
    4. 每当您对给定类执行上述任何步骤时,将变量设置为 null(适用于所有变量)

    我最终做的是创建一个类似的界面

    public interface clearMemory(){
        void clearMemory();
    }
    

    并在每个类上实现它,无论是 Activity、Fragment 还是普通类(包括适配器、自定义视图等)。

    然后我会在类被销毁时调用该方法(因为应用程序正在被销毁或每当我觉得需要这样做时。小心不要在正常运行时处理)

    @Override
    public void onDestroy(){
        clearMemory();
    }
    
    public void clearMemory(){
        normalButtonOnClickListener = null;
        normalButton.setOnClickListener(null);
        normalButton = null;
        myCustomClass.clearMemory(); // apply the interface to the class and clear it inside
        myCustomClass = null;
        simpleVariable = null;
        ...        
    }
    

    通过系统地实现这一点,我的应用程序的内存管理变得更加轻松和精简。然后,人们可以准确地知道/控制内存的处理方式和时间。

    【讨论】:

    • 谢谢,这确实有帮助。明天我会试一试(虽然我可能需要一段时间才能在整个应用程序中执行此操作),然后我会告诉你进展如何。
    • 你说清除所有变量,是指实例变量,对吧?如果我在 onCreate 方法中创建了一个变量,我是否应该在停止使用后也清除它?
    • 是的。一旦您知道不再需要它,您分配的所有东西都必须/应该立即处理。打个比方:1)你买了一张一次性纸。你在那张纸上写下关于你一天的一些事实 2) 你会用那张纸一整天,但你知道你不会永远需要这张纸 3) 到一天结束时,你意识到这张纸现在已经达到了它的目的。 4)你把纸撕开扔到垃圾桶里。现在,将“一张纸”理解为您使用的任何变量,将“一天”理解为您的活动生命周期。
    • 看起来我有很多代码重构要做:) 谢谢!一个额外的问题。您认为在 Fragment 中处理变量的最佳位置是什么?我知道 onDestroy 和 onDestroyView 可能并不总是被调用。所以现在,我正在 onStop 上做这件事。可以吗?
    • 优秀的评论。看看另一个 StackOverflow 帖子:stackoverflow.com/questions/19608948/…问候!
    【解决方案2】:

    这是对里卡多的回答的补充。

    您可以添加以下代码在 Android 中启动垃圾回收:
    Runtime.getRuntime().gc();

    注意:在将所有局部变量设为空后调用此函数。执行此代码并不能保证系统会在您的应用上进行垃圾收集,它只是暗示现在可能是执行此操作的好时机。
    我在所有活动中都使用了它onDestroy(),它似乎总是在我想要的时候起作用。
    试试看,或许能帮到你。

    【讨论】:

    • 没错。基本上可以调用 System.gc() 来“提示”系统,它最终会执行以收集所有没有引用的对象。受控内存管理始终是任何应用程序的重要组成部分!
    • 这个答案对我真的很有帮助。我一直试图在销毁时清除资源,但在启动垃圾收集后只会减少内存。谢谢。
    • 如果我在每个 popbackstack 之后调用垃圾收集器会发生什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多