在分析我的Google Cardboard应用程序时,每次使用3D图形离开活动时,我发现内存泄漏量非常大(15Mb!)。
经过长时间的严重调查后,我发现每次关闭CardboardActivity
子类时,问题的根源都是Context leak。
可以在接受的答案*
*
哇......这很尴尬......请注意任何一种(以及经验丰富的)评论者:我正在写一个问题,我已经知道了答案:我是应该为风格做点什么,比如添加一些假的悬念("我们的英雄会占上风吗?!找出接受的答案!" ),就像在一部古老的蝙蝠侠电视剧中一样还是什么?
答案 0 :(得分:2)
在切割和切片我的CardboardActivity
子类之后,除了基类之外别无其他,我不得不断定基类本身正在泄漏上下文。
我搜索了网页,发现this post解释了有问题的活动如何通过无法用类的私有实例取消注册监听器来泄露上下文。
在尝试手动调用所述方法(使用反射)时,我发现在当前版本的Cardboard SDK中(编写本文时为0.5.4),该字段不再存在。
长话短说:所有传感器现在由CardboardActivity
实例化的sensorConnection
字段作为sensorConnection
字段处理的未记录的(公共)SensorConnection类处理,该字段仍然受到详细信息中的错误的困扰我的第一个链接。
这使我得到了这个解决方案:
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(可能解决了问题),它可能会破坏(除了无所事事之外没有其他后果)一个干净的方式)。
希望这有助于某人