本文介绍了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 间接引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!