android - La actividad principal no es basura recogida después de la destrucción porque InputMethodManager hace referencia a ella indirectamente
android-activity garbage-collection (3)
Seguí el artículo "Evitando fugas de memoria" desde here .
Sin embargo, la solución propuesta no resuelve el problema de fugas. Probé esto con el emulador de Android en Windows XP (SDK 2.3.1). Dejé el montón y comprobé que la actividad principal todavía está en el montón (utilicé MAT)
Esto es lo que hice:
- crear la aplicación HelloWorld con HelloWorldActivity (no tiene vistas secundarias)
- ejecutar Emulator e iniciar la aplicación HelloWorld.
- ciérralo haciendo clic en la tecla de retroceso.
- Causa gc en DDMS y dump heap <- Aquí encontré la instancia de HelloWorldActivity.
- ''Path to GC Roots'' muestra la siguiente ruta.
HelloWorldActivity <- PhoneWindow $ DecorView <- InputMethodManager
InputMethodManager es un singleton y tres referencias a DecorView que hace referencia a HelloWorldActivity.
No puedo entender por qué InputMethodManager aún hace referencia a la instancia de DecorView incluso después de que se destruye la actividad.
¿Hay alguna forma de asegurarse de que la actividad principal se destruya y sea compatible con GC después de cerrarla?
Me he dado cuenta de que algunos oyentes tienden a mantener una referencia a la actividad en algunas circunstancias, incluso después de que la actividad supuestamente haya finalizado. Una rotación de vertical a horizontal puede, por ejemplo, reiniciar su actividad y, si es desafortunado, su primera actividad no se gc-ed correctamente (en mi caso, debido a que algunos oyentes todavía tienen una referencia).
Al ser un antiguo programador de C / C ++ lo tengo implantado en mi columna vertebral para "desactivar" a cualquier oyente en Activity.onDestroy () ( setXyzListener(null)
).
EDITAR:
Tal como lo comentó Ted a continuación, uno debería "establecer" y "desactivar" oyentes en Activity.onResume()
y Activity.onPause()
respectivamente.
Parece que llamar a los métodos de InputMethodManager ''windowDismissed'' y ''startGettingWindowFocus'' hacen las cosas.
Algo como esto:
@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);
}
Código del reflector:
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)
{
}
}
Si entiendo tu pregunta correctamente, la respuesta es: no, no puedes asegurarte de que la actividad se haya realizado. Se debe haber llamado al método onDestroy () de tu actividad y se ha cerrado la actividad. Eso no significa, sin embargo, que el proceso sea asesinado o que la actividad se realice; eso es administrado por el sistema.