CardboardActivity中的内存泄漏

时间:2015-06-24 22:56:48

标签: android memory-leaks google-cardboard

在分析我的Google Cardboard应用程序时,每次使用3D图形离开活动时,我发现内存泄漏量非常大(15Mb!)。

经过长时间的严重调查后,我发现每次关闭CardboardActivity子类时,问题的根源都是Context leak

可以在接受的答案*

中找到解决方案

*哇......这很尴尬......请注意任何一种(以及经验丰富的)评论者:我正在写一个问题,我已经知道了答案:我是应该为风格做点什么,比如添加一些假的悬念("我们的英雄会占上风吗?!找出接受的答案!" ),就像在一部古老的蝙蝠侠电视剧中一样还是什么?

1 个答案:

答案 0 :(得分:2)

在切割和切片我的CardboardActivity子类之后,除了基类之外别无其他,我不得不断定基类本身正在泄漏上下文。

我搜索了网页,发现this post解释了有问题的活动如何通过无法用类的私有实例取消注册监听器来泄露上下文。

在尝试手动调用所述方法(使用反射)时,我发现在当前版本的Cardboard SDK中(编写本文时为0.5.4),该字段不再存在。

长话短说:所有传感器现在由CardboardActivity实例化的sensorConnection字段作为sensorConnection字段处理的未记录的(公共)SensorConnection类处理,该字段仍然受到详细信息中的错误的困扰我的第一个链接。

这使我得到了这个解决方案:

  • 通过反映{/ 1}}获取CardboardActivity字段
  • 使用它来获取magneticSensor字段,再次通过反射
  • 使用setOnCardboardTheaterListener参数调用null,以清除Context Activity方法中保留对onDestroy的引用的绑定。

这归结为以下代码:

private void workAroundLeak() {
    try {
        // Get the sensor Connection
        Class<?> c1 = Class.forName("com.google.vrtoolkit.cardboard.CardboardActivity");
        Field sensorsField = c1.getDeclaredField("sensorConnection");
        sensorsField.setAccessible(true);
        SensorConnection sc = (SensorConnection) sensorsField.get(this);
        if(sc == null) return;

        // Get the magnetSensor
        Class<?> c2 = Class.forName("com.google.vrtoolkit.cardboard.sensors.SensorConnection");
        Field magnetField = c2.getDeclaredField("magnetSensor");
        magnetField.setAccessible(true);
        MagnetSensor ms = (MagnetSensor) magnetField.get(sc);
        if(ms == null) return;

        ms.setOnCardboardTriggerListener(null);
    } catch(Exception e) {}
}

@Override
protected void onDestroy() {
    workAroundLeak();
    super.onDestroy();
}

完全解决了这个问题。

明智的一句话:因为这个解决方案依赖于反思,一旦谷歌更新SDK(可能解决了问题),它可能会破坏(除了无所事事之外没有其他后果)一个干净的方式)。

希望这有助于某人