我关注了here上的“避免内存泄漏”文章。

然而,所提出的解决方案不能解决泄漏问题。我在Windows XP(SDK 2.3.1)上使用android模拟器对此进行了测试。我转储了堆并检查主 Activity 是否仍在堆中(我使用过MAT)

这是我所做的:

  • 使用HelloWorldActivity创建HelloWorld应用(无 subview )
  • 运行Emulator并启动HelloWorld应用。
  • 通过单击返回键将其关闭。
  • 导致DDMS中的gc和转储堆
  • 的“GC根目录路径”显示以下路径。

  • HelloWorldActivity
    InputMethodManager是一个单例,并包含三个对DecorView的引用,后者引用了HelloWorldActivity。

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

    有什么方法可以确保主 Activity 在关闭后被销毁并且可用于GC?

    最佳答案

    似乎调用InputMethodManager的方法“windowDismissed”和“startGettingWindowFocus”可以完成这些工作。

    像这样的东西:

    @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)
        {
        }
    }
    

    关于android - Main Activity销毁后不会进行垃圾回收,因为它是由InputMethodManager间接引用的,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5038158/

    10-09 04:57