使用setOnClickListener(this)和setOnClickListener(new View.OnClickListener(){})会导致内存泄漏。

5

我阅读了有关避免内存泄漏的文章。

为了避免与上下文相关的内存泄漏,请记住以下几点:

  • 尝试使用context-application而不是context-activity

我有两个问题:

  1. 如果我使用setOnClickListener(this),会导致内存泄漏吗?
  2. 如果我使用setOnClickListener(new View.OnClickListener(){}),会导致内存泄漏吗?
4个回答

1

1 - 如果我使用setOnClickListener(this),会导致内存泄漏吗?

不一定会导致内存泄漏,“this”实现了OnClickListener,如果你没有自己造成泄漏……例如在onClick中运行线程会导致泄漏,使用非静态内部类会导致泄漏,所以答案是setOnClickListener(this)仅在你的onClick(View view)的实现中造成泄漏时才会泄漏。

2 - 如果我使用setOnClickListener(new View.OnClickListener(){}), 会导致内存泄漏吗?

这是同样的问题,取决于你为OnClickListener.onClick实现了什么……不要泄漏实现new View.OnclickListener的类……那么就没问题了。


0

我觉得你两种方法都可以使用。不过,如果你有多个按钮(或其他控件),最好使用第一种解决方案并使用getId()来区分它们,第二种方法会为每个按钮创建一个不同的监听器(对象),所以会占用更多的内存。我认为它们都不会导致内存泄漏,因为当你销毁一个活动,并且没有留下与之相关的链接时,Java GC会将那部分内存(即监听器对象)释放给Dalvik。

希望对你有所帮助:)


0

这不会泄漏,因为 JVM 上的垃圾回收并非基于引用计数(就像 iOS 上一样),而是基于 "标记-清除" GC


0
这可能有点晚了,但我想在以上答案中添加一些内容:这取决于您在OnClickListener中正在做什么。比如说,如果您正在引用一个片段的父级 Activity,并为片段内部的一个视图设置此 OnClickListener,则您可能需要删除该引用,否则会有内存泄漏的风险。
onSettingsHeaderMenuItemClickedListener = View.OnClickListener {
            GuidedStepSupportFragment.add(requireActivity().supportFragmentManager, SettingsFragment.newInstance(), android.R.id.content)
}

例如,上面的代码正在引用父活动中的片段管理器,并且正在发生在一个片段中,因此必须清除引用,否则它将泄漏整个活动和片段!
我更喜欢使用autoCleared委托来修复这个问题,可以从Google architecture components sample中选择。
因此,当片段内部需要来自活动的引用时,整个单击侦听器的实现将类似于下面的代码:
    class SomeFragment{
        private var onSettingsHeaderMenuItemClickedListener by autoCleared<View.OnClickListener>()
        fun onViewCreated(){
            onSomethingItemClickedListener = View.OnClickListener {
                GuidedStepSupportFragment.add(requireActivity().supportFragmentManager, SettingsFragment.newInstance(), android.R.id.content)
            }
            findViewById<View>(R.id.header_item_settings).setOnClickListener(onSettingsHeaderMenuItemClickedListener)
        }
    }
    

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