Main Activity is not garbage collected after destruction because it is referenced by InputMethodManager indirectly(Main Activity 销毁后不会被垃圾回收,因为它被 InputMethodManager 间接引用)

本文介绍了Main Activity 销毁后不会被垃圾回收,因为它被 InputMethodManager 间接引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从 这里.

但是,建议的解决方案并不能解决泄漏问题.我在 Windows XP (SDK 2.3.1) 上使用 android 模拟器对此进行了测试.我转储了堆并检查了主要活动仍在堆中(我使用了 MAT)

However the proposed solution does not solve the leak problem. I tested this with android emulator on Windows XP (SDK 2.3.1). I dumped the heap and checked the main activity is still in the heap (I used MAT)

这就是我所做的:

  1. 使用 HelloWorldActivity 创建 HelloWorld 应用(它没有子视图)
  2. 运行模拟器并启动 HelloWorld 应用.
  3. 点击后退键将其关闭.
  4. Cause gc in DDMS and dump heap <-- 这里我找到了HelloWorldActivity实例.
  5. 'Path to GC Roots' 显示以下路径.

HelloWorldActivity <- PhoneWindow$DecorView <- InputMethodManager

HelloWorldActivity <- PhoneWindow$DecorView <- InputMethodManager

InputMethodManager 是一个单例和三个对引用 HelloWorldActivity 的 DecorView 的引用.

InputMethodManager is a singleton and three references to DecorView which references HelloWorldActivity.

我不明白为什么 InputMethodManager 即使在 Activity 被销毁后仍然引用 DecorView 实例.

I can't understand why InputMethodManager still references DecorView instance even after the activity is destroyed.

有什么方法可以确保主要活动在关闭后被销毁并可以进行GC?

Is there any way to make sure that the main activity is destroyed and GC-able after closing it?

推荐答案

似乎调用 InputMethodManager 的方法 'windowDismissed' 和 'startGettingWindowFocus' 可以解决问题.

It seems that calling InputMethodManager's methods 'windowDismissed' and 'startGettingWindowFocus' do the stuff.

类似这样的:

@Override
protected void onDestroy()
{
    super.onDestroy();
    //fix for memory leak: http://code.google.com/p/android/issues/detail?id=34731
    fixInputMethodManager();
}

private void fixInputMethodManager()
{
    final Object imm = getSystemService(Context.INPUT_METHOD_SERVICE);

    final Reflector.TypedObject windowToken
        = new Reflector.TypedObject(getWindow().getDecorView().getWindowToken(), IBinder.class);

    Reflector.invokeMethodExceptionSafe(imm, "windowDismissed", windowToken);

    final Reflector.TypedObject view
        = new Reflector.TypedObject(null, View.class);

    Reflector.invokeMethodExceptionSafe(imm, "startGettingWindowFocus", view);
}

反射器代码:

public static final class TypedObject
{
    private final Object object;
    private final Class type;

    public TypedObject(final Object object, final Class type)
    {
    this.object = object;
    this.type = type;
    }

    Object getObject()
    {
        return object;
    }

    Class getType()
    {
        return type;
    }
}

public static void invokeMethodExceptionSafe(final Object methodOwner, final String method, final TypedObject... arguments)
{
    if (null == methodOwner)
    {
        return;
    }

    try
    {
        final Class<?>[] types = null == arguments ? new Class[0] : new Class[arguments.length];
        final Object[] objects = null == arguments ? new Object[0] : new Object[arguments.length];

        if (null != arguments)
        {
            for (int i = 0, limit = types.length; i < limit; i++)
            {
                types[i] = arguments[i].getType();
                objects[i] = arguments[i].getObject();
            }
        }

        final Method declaredMethod = methodOwner.getClass().getDeclaredMethod(method, types);

        declaredMethod.setAccessible(true);
        declaredMethod.invoke(methodOwner, objects);
    }
    catch (final Throwable ignored)
    {
    }
}

这篇关于Main Activity 销毁后不会被垃圾回收,因为它被 InputMethodManager 间接引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!