【问题标题】:(AudioManager)getSystemService(Context.AUDIO_SERVICE) causing memory leak(AudioManager)getSystemService(Context.AUDIO_SERVICE) 导致内存泄漏
【发布时间】:2013-11-27 13:52:05
【问题描述】:

我遇到了由 AudioManager 引起的内存泄漏。所以我在我的代码中注释掉了这一行,看看它是否能解决我的问题:

public class FireRoomActivity extends Activity {

AudioManager am;
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
  }
}

它确实解决了问题,我不再有内存泄漏。那是因为 Context.AUDIO_SERVICE 吗?如果是,那我该如何替换它?

如果重要的话,我的 Activity 中有这个非静态类,它不会在外面的其他地方使用

class GestureListener extends GestureDetector.SimpleOnGestureListener {
RelativeLayout parentLayout;

public void setLayout(RelativeLayout layout){
    parentLayout = layout;  }
@Override
public boolean onDown(MotionEvent e) {
    return true;
}
// event when double tap occurs
@Override
public boolean onDoubleTap(MotionEvent e) {     
    makeArrowsVisible();
    parentLayout.findViewById(R.id.cabinet_zoomed).setVisibility(View.INVISIBLE);
    Button key = (Button)parentLayout.findViewById(R.id.key);
    if(key!=null){
        key.setVisibility(View.INVISIBLE);}
    return true;
}

编辑: 堆转储的屏幕截图

【问题讨论】:

  • 发布让你相信你有内存泄漏的实际证据。

标签: android memory-leaks android-audiomanager


【解决方案1】:

https://gist.github.com/jankovd/891d96f476f7a9ce24e2 中提到的修复对我有用。

public class ActivityUsingVideoView extends Activity {

  @Override protected void attachBaseContext(Context base) {
    super.attachBaseContext(AudioServiceActivityLeak.preventLeakOf(base));
  }
}


/**
 * Fixes a leak caused by AudioManager using an Activity context. 
 * Tracked at https://android-review.googlesource.com/#/c/140481/1 and
 * https://github.com/square/leakcanary/issues/205
 */
public class AudioServiceActivityLeak extends ContextWrapper {

  AudioServiceActivityLeak(Context base) {
    super(base);
  }

  public static ContextWrapper preventLeakOf(Context base) {
    return new AudioServiceActivityLeak(base);
  }

  @Override public Object getSystemService(String name) {
    if (Context.AUDIO_SERVICE.equals(name)) {
      return getApplicationContext().getSystemService(name);
    }
    return super.getSystemService(name);
  }
}

感谢德扬·扬科夫 :)

【讨论】:

    【解决方案2】:

    您可以使用应用程序上下文来避免内存泄漏来获取音频服务。

    【讨论】:

    • 虽然这也是我的第一个猜测,但我惊讶地发现它不起作用(至少在我的特定情况下不是)。经过一番研究,我最终得出了以下答案中发布的结论...
    【解决方案3】:

    我在另一篇文章中发现 AudioManager 确实保留了强引用,但仍会被正确地进行垃圾收集。见this google group conversation。这是我从中得到的:

    这意味着,如果您在 Eclipse 中的 DDMS 选项卡中手动启动几个垃圾收集,就在进行磁头转储之前,则该引用不应该再存在了。

    这确实解决了我的“问题”,因为它毕竟不是问题......

    还提到调试器不应挂机(即使用 Run As... 而不是 Debug As...)。处于活动状态的调试器可能会导致 AudioManager 持有引用,从而造成堆溢出(我尚未测试此确认)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-06
      • 2014-06-07
      • 2013-11-20
      • 2011-10-28
      • 2016-01-18
      • 2012-12-13
      • 1970-01-01
      • 2011-01-08
      相关资源
      最近更新 更多