Liberar recursos en onPause en lugar de onDestroy
Se trata de POST-nido de abeja (es decir, Android 3.0 +) y las citas a continuación vienen de https://developer.android.com/reference/android/app/Activity.html
Según el ciclo de vida, onStop y onDestroy son killable, esto significa:
- ¿Cuál es el fragmento equivalente de Activity.isFinishing ()?
- cómo comprobar si una actividad implementa una interfaz después de onAttach (Activity activity) ha sido depreciada
- ¿Cuánto dura un paquete?
- La aplicación se reinicia en lugar de continuar
- Manejo de cambios de configuración de UI automática en Actividad y Fragmento falla a veces
Observe la columna "Killable" en la tabla anterior – para aquellos métodos que están marcados como killable, después de que el método devuelve el proceso que aloja la actividad puede ser destruido por el sistema en cualquier momento sin que se ejecute otra línea de su código
-
En otras palabras, onStop (a lo largo de los otros que se producen antes de este evento) está garantizado para ser llamado, pero en el momento en que el método vuelve, el proceso podría morir, por lo que onDestroy no se garantiza que se llame.
Otra cita dice:
Para aquellos métodos que no están marcados como matables, el proceso de la actividad no será eliminado por el sistema a partir del momento en que se llama al método y continúa después de que regrese.
Seguido por
Por lo tanto, una actividad está en el estado eliminable , por ejemplo, entre después onPause () hasta el inicio de onResume ().
-
Pero esto no corresponde a lo dicho anteriormente, a menos que esto sólo corresponda a PRE-panal . Esto no es cierto para POST-nido de abeja , ¿verdad? Así que, básicamente, tanto onPause y onStop están garantizados para ser llamado.
-
Suponiendo que sólo libero un recurso en onDestroy, entonces esto podría conducir a una posible fuga ya que onDestroy podría no ser llamado, ¿verdad?
-
Sin embargo, este escenario (es decir, onDestroy no se llama) ocurre además cuando el proceso es asesinado por el propio Android? ¿Existen otros escenarios que causen que onDestroy no se llame, por lo que se pierde el recurso .
-
¿Es cierto que cuando Android mata el proceso que los recursos serán destruidos y no se puede producir una fuga (incluso cuando no explícitamente lanzado el recurso?).
Sírvanse proporcionar información detallada sobre si esas afirmaciones (1) (2) (3) (4) (5) son correctas o no.
- ¿Cómo tratar los datos retenidos después de que la actividad llegue a primer plano cuando se utiliza más de una actividad?
- Reiniciar una actividad ya en ejecución
- ¿Este patrón de mensajería de Servicio de Actividad causa una pérdida de memoria?
- NullPointerException en Fragment Listener
- OnActivityCreated siempre se llama?
- La mejor manera de implementar Socket.io en android
- La aplicación se bloquea en rotación sin stackTrace
- ¿Por qué se definen los métodos del ciclo de vida en la clase de actividad con el especificador de acceso protegido
En primer lugar vamos a entender lo que está pasando con la documentación que citó.
Los siguientes comandos muestran la salida de git blame
del archivo Activity.java
en AOSP:
$ cd $AOSP/frameworks/base $ git blame ./core/java/android/app/Activity.java
La parte relevante de la salida:
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 363) * <p>Note the "Killable" column in the above table -- for those methods that 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 364) * are marked as being killable, after that method returns the process hosting the 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 365) * activity may killed by the system <em>at any time</em> without another line 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 366) * of its code being executed. Because of this, you should use the 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 367) * {@link #onPause} method to write any persistent data (such as user edits) 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 368) * to storage. In addition, the method 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 369) * {@link #onSaveInstanceState(Bundle)} is called before placing the activity 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 370) * in such a background state, allowing you to save away any dynamic instance 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 371) * state in your activity into the given Bundle, to be later received in 550116576 (RoboErik 2014-07-09 15:05:53 -0700 372) * {@link #onCreate} if the activity needs to be re-created. 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 373) * See the <a href="#ProcessLifecycle">Process Lifecycle</a> 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 374) * section for more information on how the lifecycle of a process is tied 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 375) * to the activities it is hosting. Note that it is important to save 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 376) * persistent data in {@link #onPause} instead of {@link #onSaveInstanceState} 5c40f3fcc (Daisuke Miyakawa 2011-02-15 13:24:36 -0800 377) * because the latter is not part of the lifecycle callbacks, so will not 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 378) * be called in every situation as described in its documentation.</p> 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 379) * 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 380) * <p class="note">Be aware that these semantics will change slightly between 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 381) * applications targeting platforms starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB} 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 382) * vs. those targeting prior platforms. Starting with Honeycomb, an application 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 383) * is not in the killable state until its {@link #onStop} has returned. This 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 384) * impacts when {@link #onSaveInstanceState(Bundle)} may be called (it may be 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 385) * safely called after {@link #onPause()} and allows and application to safely 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 386) * wait until {@link #onStop()} to save persistent state.</p> 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 387) * 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 388) * <p>For those methods that are not marked as being killable, the activity's 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 389) * process will not be killed by the system starting from the time the method 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 390) * is called and continuing after it returns. Thus an activity is in the killable 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 391) * state, for example, between after <code>onPause()</code> to the start of 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 392) * <code>onResume()</code>.</p>
Tenga en cuenta que el párrafo que analiza el comportamiento después de Honeycomb fue añadido por Dianne Hackborn el 2010-12-07, mientras que los párrafos adjuntos datan de 2009-03-03.
Lo que nos dice es que Dianne agregó el nuevo párrafo sin actualizar el resto del javadoc, por lo tanto la contradicción. Desafortunadamente, esto no es raro en Android.
A sus preguntas:
1) En post-Honeycomb versiones de Android tanto onResume()
y onStop()
están garantizados para ser llamado (como se indica por Dianne Hackborn en su adición a la actividad javadoc).
2) En pre-Honeycomb sólo onPause()
se garantiza que se llamará (como se indica en la versión anterior de la actividad de javadoc)
3,4,5) onDestroy()
no se llamará sólo si el proceso que aloja toda la aplicación es eliminado. Cuando el proceso se destruye, todos los recursos asignados a él se liberan, por lo tanto, no hay riesgo de pérdida de memoria en este caso.
Nota importante : dado que la liberación de recursos en onDestroy()
no causará pérdida de memoria, podría parecer una buena idea poner todo el código de "liberación" allí. Sin embargo, rara vez es el enfoque óptimo. ¿Por qué? Lee abajo.
Cuando la Activity
pasa al fondo se detiene, pero no se destruye (normalmente). Activity
puede permanecer en este estado "detenido" durante bastante tiempo, y se iniciará de nuevo si el usuario vuelve a la aplicación. Si libera recursos en onDestroy()
, que no se llama de forma predeterminada cuando la Activity
pasa al fondo, la Activity
se mantendrá en estos recursos mientras está en estado detenido, lo que provocará una mayor cantidad de recursos consumidos por la aplicación en el estado de fondo.
Cuando Android se queda sin memoria, comienza a matar los procesos para liberar la memoria consumida por ellos. Una de las consideraciones más importantes tomadas en cuenta al elegir qué procesos matar es su consumo de recursos. Por lo tanto, si su aplicación se mantiene a los recursos en estado de fondo detenido, tendrá una mayor probabilidad de ser asesinado por Android.
Además, nosotros, los desarrolladores, debemos asegurarnos de que hacemos las mejores aplicaciones para nuestros usuarios. La aplicación que consume una cantidad no mínima de recursos del teléfono del usuario y de la batería mientras está en segundo plano no es una buena aplicación. ¡Y los usuarios lo sabrán!
Por lo tanto, onStop()
fuertemente la liberación de todos los recursos en el método onStop()
. Normalmente no sobrescribo métodos onDestroy()
en Activities
y Fragments
en absoluto.
Corolario: Como señalado por @Juan en su comentario, la importante nota anterior tiene un corolario igualmente importante, pero no tan evidente: onStart()
debería ser el único método en el que se asignan los recursos. Sea cual sea su definición de "recursos", ni onCreate()
ni onResume()
deben asignar estos recursos.
Creo que Vasily proporcionó una gran respuesta. Todavía hay un punto pequeño pero importante que falta allí relacionado con
- ¿Es cierto que cuando Android mata el proceso que los recursos serán destruidos y no se puede producir una fuga (incluso cuando no explícitamente lanzado el recurso?).
La respuesta depende de qué es exactamente lo que usted tiene miedo. Como Vasily señaló Android (que se basa en Linux) es un sistema operativo seguro moderno que garantiza que cuando el proceso es asesinado, toda la memoria será liberada, además todos los archivos abiertos, conexiones de red, etc también se cerrarán correctamente. Así que no habrá fugas de recursos en el sentido usual.
Todavía hay un escenario potencialmente problemático. Supongamos que tiene alguna lógica que realiza cuando libera algún recurso, es decir, algo que pondría en un destructor en C ++ o en una implementación de Closeable.close
en Java. Por ejemplo, tiene un caché en la memoria que retrasa escribe en un archivo con batching. Normalmente descarga la caché en memoria en onDestroy
y todo funciona bien. Pero cuando el proceso es forzado por Android, onDestroy
puede no ser llamado y su lógica de descarga no se ejecuta y por lo tanto puede perder algunos datos y / o tener un estado no válido en su almacenamiento persistente. Así que si tienes algo como esto, debes asegurar la consistencia realizando esa lógica en un lugar más confiable: onPause
o onStop
.
- Android: layout_marginBottom no parece funcionar correctamente en 2.2 (Froyo)
- Abrir archivo html local con el navegador de Android