首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >android.widget.BubblePopupHelper引起的内存泄漏

android.widget.BubblePopupHelper引起的内存泄漏
EN

Stack Overflow用户
提问于 2014-12-03 08:41:23
回答 1查看 916关注 0票数 5

我正在使用MemoryAnalyzer工具来查找我的Android应用程序中的内存泄漏。因此,我运行我的应用程序,访问所有的活动,然后按下,直到我到达桌面。然后使用DDMS获得内存转储(多次按导致GC )。

然后使用OQL查询select * from instanceof android.app.Activity查找泄漏活动,然后按下合并最短路径到Shortest ->,排除泄漏对象上的所有幻影/弱/软/etc引用。这张照片是:

因此,系统中的某个地方似乎有一个静态对象BubblePopupHelper.sHelper,它保留了对我的活动中的EditText视图的引用,从而导致整个活动泄漏!但这是什么BubblePopupHelper?我在官方文件中找不到关于这个类的任何信息。我怎样才能防止我的活动因为被这个奇怪的对象引用而被保存在记忆中呢?

我在LG L40设备上进行测试,运行API19

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-12 16:24:14

我的检漏工具定期报告同样的泄漏,只有LG手机:

代码语言:javascript
复制
object com.squareup.SomeActivity
`-mContext of object android.widget.EditText
  `-mView of object android.widget.BubblePopupHelper
    `-sHelper of class android.widget.BubblePopupHelper

制造商喜欢在幕后修改Android的私有API。这是LG引入的内存泄漏。

据我所知,聚焦EditText使用该BubblePopupHelper,可能是为了显示某些复制/粘贴弹出窗口或文本句柄。因为一次只有一个焦点集中的编辑文本,所以他们使助手成为一个单例,并且它保留了一个针对最新编辑文本的引用。

因此,这意味着整个活动&它的整个视图层次结构都会泄漏,直到另一个编辑文本获得焦点。

你怎么能解决这个问题?遗憾的是,这是SDK代码,因此,虽然这可能会在LG的未来版本中修复,但总会有一些用户使用该bug。

虽然这个错误肯定不是您的错,但它仍然是内存泄漏,可能会泄漏到增加的OutOfMemory错误。所以,这是值得一试的,

有个办法,但不漂亮。当活动被销毁时,您可以使用反射清除泄漏。例如,一种方法可以是清除sHelper字段,或者另一种方法是清除助手上的mView字段。不管是哪种方式,你都应该在设备上试一试(我现在还没有),看看它是否有效。

代码语言:javascript
复制
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) {
          }
        }
      });
    }
  });
}
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27267071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档