android android-activity garbage-collection inputmethodmanager

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:

  1. crear la aplicación HelloWorld con HelloWorldActivity (no tiene vistas secundarias)
  2. ejecutar Emulator e iniciar la aplicación HelloWorld.
  3. ciérralo haciendo clic en la tecla de retroceso.
  4. Causa gc en DDMS y dump heap <- Aquí encontré la instancia de HelloWorldActivity.
  5. ''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.