【问题标题】:Memory leak with setOnClickListener(this) and setOnClickListener(new View.OnClickListener(){})setOnClickListener(this) 和 setOnClickListener(new View.OnClickListener(){}) 的内存泄漏
【发布时间】:2012-09-23 13:10:14
【问题描述】:

我读到了avoiding memory leaks

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

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

我有两个问题:

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

【问题讨论】:

    标签: android memory-leaks


    【解决方案1】:

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

    没有必要,“this”实现了 OnClickListener,如果你自己不泄漏...例如在 onClick 中运行线程会泄漏,使用非静态内部类会泄漏,所以答案是 setOnClickListener(this) 只有在您的 onClick(View view) 实现泄漏时才会泄漏。

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

    是同一个问题,取决于您为 OnClickListener.onClick 实现了什么...如果您实现了 new View.OnclickListener...,请不要泄漏该类,您会没事的。

    【讨论】:

      【解决方案2】:

      我会说你可以同时使用两者。虽然,如果您有多个按钮(或任何其他小部件),最好使用带有 getId() 的第一个解决方案来区分它们,第二个解决方案为每个按钮创建一个不同的侦听器(对象),因此它保留更多内存。我认为它们中的任何一个都不会导致内存泄漏,因为当您销毁一个活动并且没有为它留下任何链接时,java GC 会将该内存(侦听器对象)归还给 dalvik。

      希望对你有帮助:)

      【讨论】:

        【解决方案3】:

        这可能有点晚了,但我想将其添加到上面的答案中:这取决于您在 OnClickListener 中做什么,假设您引用的是片段的父 Activity并且您正在将此 OnClickListener 设置为片段内的视图,那么您可能需要删除您的引用,否则您有泄漏内存的风险:

        onSettingsHeaderMenuItemClickedListener = View.OnClickListener {
                    GuidedStepSupportFragment.add(requireActivity().supportFragmentManager, SettingsFragment.newInstance(), android.R.id.content)
        }
        

        例如,上面的代码引用了父activity内部的fragment manager,并且发生在一个fragment中,所以这个引用必须被清除,否则会泄漏整个activity和fragment!

        我更喜欢使用我可以从 Google architecture components sample 中选择的 autoCleared 委托来解决此问题。

        因此,当在片段内并需要来自活动的引用时,单击侦听器的整个实现将类似于以下代码:

            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)
                }
            }
            
        

        【讨论】:

          猜你喜欢
          • 2017-09-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多