我正在使用MemoryAnalyzer工具在我的Android应用程序中查找内存泄漏。因此,我运行我的应用程序,访问所有活动,然后按回去直到进入桌面。然后,我使用DDMS进行内存转储(多次按下原因GC)。
然后,我使用OQL查询select * from instanceof android.app.Activity
查找泄漏的活动,然后按合并GC根的最短路径->排除泄漏对象上的所有幻像/弱/软/等引用。这是这张图片:
因此,似乎在系统中的某个位置存在一个静态对象BubblePopupHelper.sHelper
,该对象保留了EditText
我的活动对视图的引用,从而导致整个活动泄漏!但是,这是什么BubblePopupHelper
?我在官方文档中找不到有关此类的任何信息。以及如何防止由于此奇怪对象引用我的活动而将其保留在内存中?
我正在运行API19的LG L40设备上进行测试
我的泄漏检测工具定期报告相同的泄漏,仅来自LG手机:
object com.squareup.SomeActivity
`-mContext of object android.widget.EditText
`-mView of object android.widget.BubblePopupHelper
`-sHelper of class android.widget.BubblePopupHelper
制造商喜欢在后台更改Android SDK的私有API。这是LG引入的内存泄漏。
据我所知,重点突出的EditText使用了BubblePopupHelper,可能显示了一些复制/粘贴弹出窗口或文本句柄。由于一次只能有一个重点突出的编辑文本,因此他们使助手变成单例,并且它始终引用最新重点突出的编辑文本。
因此,这意味着整个活动及其整个视图层次结构都将泄漏,直到另一个编辑文本成为焦点为止。
您该如何解决?可悲的是,这是SDK代码,因此尽管在LG的将来版本中可能会修复此问题,但始终会有一些用户遇到该错误。
尽管此错误当然不是您的错,但它仍然是内存泄漏,可能会泄漏到增加的内存不足错误。因此,值得尝试修复它,
有办法,但不是很漂亮。活动被破坏后,可以使用反射清除泄漏。例如,一种方法可能是清除sHelper字段,或者另一种方法是清除辅助程序上的mView字段。无论哪种方式,您都应该在设备上尝试一下(我现在没有),然后看看它是否有效。
private static final Executor backgroundExecutor =
newCachedThreadPool(backgroundThreadFactory("android-leaks"));
public static void fixLGBubblePopupHelper(final Application application) {
backgroundExecutor.execute(new Runnable() {
@Override public void run() {
final Field sHelperField;
try {
Class<?> bubbleClass = Class.forName("android.widget.BubblePopupHelper");
sHelperField = bubbleClass.getDeclaredField("sHelper");
sHelperField.setAccessible(true);
} catch (Exception ignored) {
// We have no guarantee that this class / field exists.
return;
}
application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacksAdapter() {
@Override public void onActivityDestroyed(Activity activity) {
try {
sHelperField.set(null, null);
} catch (IllegalAccessException ignored) {
}
}
});
}
});
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句