首页 > 解决方案 > 更换片段时内存泄漏

问题描述

我刚刚开始使用 LeakCanary,当我更换 Fragment 时,每次泄漏都会增加。这是 LeakCanary 报告:

android.widget.LinearLayout instance
​     Leaking: YES (ObjectWatcher was watching this because com.home.app1.PostFragment received Fragment#onDestroyView() callback 
     (references to its views should be cleared to prevent leaks))

这是我的片段替换代码:

public void change(Fragment fragment) {

    ((FragmentActivity) context).getSupportFragmentManager().beginTransaction()

            .replace(R.id.frameLayout, fragment, "fragment")
            .setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
            .addToBackStack(null)
            .commit();
}

所以我对 SO 进行了研究,有人说意见必须在onDestroyView. 然后我尝试了这个onDestroyViewfragmentView=null;但没有任何改变。也试过这个:

if (view.getParent() != null) {
        ((ViewGroup) view.getParent()).removeView(view);
    }

但再次没有任何改变。所以我试图让所有视图都为空,如下所示:

   @Override
   public void onDestroyView() {
    super.onDestroyView();
    backButton=null;
    swipeLayout=null;
    imageView=null; ...etc.
   }

最终,LeakCanary 上的泄漏警告消失了。但我认为这不是一个解决方案,也没有意义,因为可能有很多意见。那么避免这种泄漏的解决方案是什么?谢谢。

标签: javaandroidandroid-fragmentsmemory-leaksleakcanary

解决方案


所以我试图让所有视图都为空,如下所示

最终,LeakCanary 上的泄漏警告消失了。

View您已经找到了解决方案 - 在引用(您的backButtonswipeLayoutimageView等)被删除并应该被销毁 ( ) 之后,您一直在持有它们onDestroyView。由于持有对它们的引用可以防止它们被垃圾收集,这就是内存泄漏。

但我认为这不是一个解决方案,也没有意义,因为可能有很多意见。那么避免这种泄漏的解决方案是什么?

如果您View手动将 s 存储在成员变量中,那是最好的解决方案。您可以findViewById每次都使用它来查找它,但我不推荐它,因为重复遍历视图层次结构会导致性能损失。

您可以通过使用Android 开发工具的视图绑定功能来避免这两个问题。有了它,您将只需摆脱一个 Binding 对象。

您还可以使用Butter Knife为您管理视图变量 - 请参阅unbinder.unbind();该页面上提到的模式。


推荐阅读