para - manual android studio avanzado
Ciclo de vida de la actividad de Android más simple (9)
¡Creo que he encontrado lo que estoy buscando! (Me 1, Bono 0)
Esto es para una sola actividad de ''Juego'' que usa métodos mínimos para controlar un hilo de ''GameThread'' que maneja el juego. Utiliza una clase adicional de ''GameData'' para almacenar datos que deben ser persistentes entre activaciones.
Si la aplicación pierde el enfoque (es decir, una llamada telefónica entrante o si el usuario hace clic en regresar, etc.), Game guarda los datos del juego en un archivo y sale. Para reanudar, simplemente inicie la aplicación de nuevo y volverá a donde lo dejó.
El archivo de diseño ''game.xml'' es un SurfaceView que cubre toda la pantalla
Juego.java:
- onCreate configura SurfaceHolder para SurfaceView y crea el GameThread
- surfaceChanged llama a GameThread.startThread para iniciar GameThread, si aún no se ha iniciado, pasando el tamaño de la pantalla
- onPause llama a GameThread.endThread para finalizar GameThread y finaliza esta actividad
- onTouch pasa eventos táctiles al método GameThread.doTouch
GameThread.java:
- startThread configura los datos retenidos localmente, carga GameData del archivo e inicia el hilo
- run es un bucle de juego estándar, que llama rutinas de actualización de Física y sorteo bastante estándar para cada fotograma. Una vez finalizado el bucle de juego, guarda el GameData en el archivo
- endThread detiene el ciclo de juego en ejecución y espera a que finalice
- Las acciones doTouch tocan eventos de la actividad del juego.
Parece funcionar. Significa tener que manejar diferentes pantallas (p. Ej., Pantalla de título, opciones, juego y juego finalizado) en un hilo, pero eso no es el fin del mundo, IMHO.
Tal vez publique el código en CodeReview (lo actualizaré si lo hago) y veré si alguien tiene algún comentario. Mientras tanto, ¡será mejor que programe los próximos Angry Birds!
Noté que la sección de Actividad para Desarrolladores de Android se ha actualizado desde que inicié mi aplicación, pero todavía no estoy claro cuál es el Ciclo de Vida de la Actividad más simple.
Por lo que puedo distinguir:
onCreate, onResume y onPause son los esenciales.
La actividad se puede eliminar en cualquier momento después de onPause, por lo que debo guardar todo el estado de la aplicación en un archivo onPause y no confiar en onStop o onDestroy. Además, no se llama a onSaveInstanceState antes de cada onPause, por lo que realmente no vale la pena usarlo.
En lugar de intentar escribir un montón de código para manejar todos los escenarios, ¿por qué no destruir la Actividad al final de su onPause?
El ciclo de vida sería entonces onCreate y onResume antes de que esté activo, y luego onPause cuando esté inactivo. No se necesitarían otros métodos.
Usaría onCreate para llamar a setContentView y configurar escuchas de vista, pero todo lo demás se pondría en el currículum, incluida la carga del estado restaurado de un archivo. Como se indicó anteriormente, onPause guardaría el estado en un archivo y destruiría la actividad.
Por lo que puedo ver, la única desventaja de esto podría ser que cuando una ventana emergente está en la pantalla, la actividad se elimina y debe recrearse cuando la ventana emergente está cerrada, lo que significa que la actividad no será visible detrás de la ventana emergente (aunque No he probado esto)
Es posible que tarde un poco más en reiniciar la actividad, pero como el sistema podría haber eliminado la actividad de todos modos sin previo aviso, debe guardar todo el estado de todos modos.
¿Alguna idea?
Actualización: Supongo que en lo que estaba pensando era cuando una actividad de "portada" llama una actividad de juego. La actividad de la página principal llamaría a la actividad del juego cuando el jugador haga clic en "Jugar"
La actividad del juego configuraría sus vistas y oyentes, etc. en onCreate, y en onResume cargaría un archivo que contenía el estado del juego, o comenzaría un juego nuevo si no existía ningún archivo.
En la pausa del juego, escribe el estado del juego en el archivo, luego, lo que suceda con la actividad del juego (nada, o se detiene / destruye, o lo que sea), el método onResume siempre volverá a cargar todos los datos desde el archivo.
Eso es algo de lo que estaba pensando, si eso tiene algún sentido?
Update2: He ideado una solución simple que he documentado en una respuesta a continuación, ¡si alguien está interesado!
No es compatible con los estados de "Actividad en pausa" y "Detenido" del ciclo de vida de Android. Una vez que ya no se muestra, se mata a sí mismo y debe reiniciarse manualmente, ¡pero continúa desde donde lo dejó!
¿Estás buscando esto?
Para responder aún más a su pregunta, sí, como puede ver claramente en el diagrama anterior, el ciclo de vida "más simple" (es decir, el menor número de llamadas a métodos) de hecho es onCreate(); onStart(); onResume(); onPause();
onCreate(); onStart(); onResume(); onPause();
.
También debe saber sobre onSaveInstanceState()
y onRetainNonConfigurationInstance()
. Estos NO son métodos de ciclo de vida.
Todos estos métodos están muy bien documentados. Por favor, lea esta documentación detenidamente.
Para aclarar aún más las cosas, aquí hay un par de escenarios de la vida real:
- La actividad se está ejecutando, otras actividades se
onPause
, se llamaonPause
. El sistema se queda sin memoria, llamaonSaveInstanceState
, mata la actividad. El usuario presionó hacia atrás unas cuantas veces, la actividad debe volver a crearse una instancia (preferiblemente utilizando los datos guardados enonSaveInstanceState
). - La actividad se está ejecutando, el usuario presiona hacia atrás. En este punto, se llama a
onPause->onDestroy
, sin llamaronSaveInstanceState
.
Debe comprender la diferencia esencial entre onPause
y onSaveInstanceState
. Siempre se llama al primero, mientras que al segundo solo se llama cuando la instancia de actividad se puede volver a crear una instancia en el futuro. Siguiendo esta línea de pensamiento, sus usuarios esperarán dos cosas:
- Cuando se alejan de su Actividad y luego vuelven a ella, la quieren exactamente en el mismo momento en que la dejaron (esto se lograría utilizando
onSaveInstanceState
). No esperan eso si salen de tu actividad. Sin embargo: -
onPause
que los datos que ingresaron seonPause
(lo que se hará en unaonPause
). Por ejemplo, si comenzaron a redactar un mensaje, esperarán verlo como borrador la próxima vez que regresen, incluso si abandonan la actividad.
Debe comprender cómo se supone que deben utilizarse estos métodos para obtener lo que sus usuarios esperan. La forma en que realmente los use depende de usted, sus necesidades y la naturaleza de su aplicación.
El sistema Android está manejando el ciclo de vida: es decir, instanciando actividades y llamando a los métodos del ciclo de vida. Así que no sé lo que quieres decir con "destruir la actividad". Tú, como desarrollador, no tienes tal habilidad.
En segundo lugar, el flujo del ciclo de vida de la actividad a veces puede ser confuso (sé que luché con él al principio). Por lo tanto, simplemente implemente todos los métodos de ciclo de vida y coloque las declaraciones de registro en ellos. Luego intente todos los casos de uso de la vida real (incluida la recepción de una llamada durante el uso de la aplicación) para ver cómo se llaman los métodos del ciclo de vida.
Estaba estudiando el ciclo de vida de la actividad y el proceso completo de lo que sucede al iniciar cualquier actividad, a partir de onCreate
. Aquí hay un diagrama UML para ayudarte.
Haga clic en este enlace para ver una versión de alta resolución .
Hay 7 métodos que administran el ciclo de vida de la actividad en la aplicación de Android:
- onCreate ()
- onStart ()
- En resumen()
- onRestart ()
- en pausa ()
- onStop ()
- onDestroy ()
He escrito más a fondo sobre estos métodos en mi blog.
La aplicación de Android madura, con todas las funciones y funcional completa se transfiere (estado = función de tiempo) de acuerdo con la respuesta proporcionada por @Felix.
Pero qué pasa si solo quieres crear una aplicación que ni siquiera tiene GUI. Y quieres el ciclo de vida más simple, entonces tengo la respuesta a continuación.
Esta respuesta probablemente la encontraras interesante. El sistema Android después de leer AndroidManifest.xml sabe cuál es el punto de entrada. Cualquiera que sea la actividad tiene esto
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
será el punto de inicio o entrada para que comience el sistema. Después de esto, el proceso de la aplicación obtuvo la memoria donde se puede iniciar.
La creación de su proceso principal es la tarea del sistema Android. Cuando un componente de la aplicación se inicia y la aplicación no tiene otros componentes en ejecución, el sistema Android inicia un nuevo proceso de Linux. Después de que el proceso llama a onCreate () , crea un hilo principal. Esa es la razón por la que debe llamar a onCreate () , porque el hilo principal se inicializa y el hilo principal es el desencadenante de todas sus acciones futuras.
En onCreate (), tienes tu hilo principal. Después de eso, depende totalmente de usted, a qué devolución de llamadas desea llamar. No hay ninguna regla a la que deba llamar onStart () después de onCreate ().
Solo un método de ciclo de vida onCreate () está garantizado como el ciclo de vida de sus componentes.
Y, además, para comprender qué es lo que cada método de ciclo de vida está haciendo dentro de él, coloque el siguiente código.
//add the log line
Log.i(this.getClass().getCanonicalName(), "##############");
int count = 0;
for (StackTraceElement stackTraceElement: Thread.currentThread().getStackTrace()) {
count++;
Log.i(this.getClass().getCanonicalName(), "/""+Thread.currentThread().getStackTrace()[2].getMethodName()+"/" "+count+" "+stackTraceElement.getMethodName());
}; //end of log line
Por lo tanto, siempre agregue sobre el mismo código para ver los registros en la consola de log cat.
Cuando la aplicación inicia la GUI, llama a OnStart (). Si no llama al método super () dentro de la devolución de llamada, el sistema Android muestra un error de tubería rota y no puede seguir procesando y depurando.
Pero, puede implementar su propia lógica dentro de cada método de devolución de llamada. Por ejemplo, puede hacer la suma de dos números en onStart ().
Por lo tanto, todos los métodos de devolución de llamada de Android son métodos parcialmente implementados. No son métodos puramente abstractos porque deberías llamar el método super () dentro de ellos .
La imagen adjunta indica: El proceso principal de la aplicación llama onCreate (), delega sus responsabilidades al hilo principal (hilo de la interfaz de usuario) y el hilo principal llama a estas otras 16 devoluciones de llamada.
Además, si desea ver todos sus métodos en un momento determinado, coloque este código a continuación.
//to see all the methods (including super methods) at this time, you call use the java reflection as below
Log.i(this.getClass().getCanonicalName(), "##############");
int count1 = 0;
for (Method method: this.getClass().getMethods()) {
count1++;
count++;
Log.i(this.getClass().getCanonicalName(), count1+" "+method);
}; //end of log line
//At another time, after you add some other methods or android using GC removes some methods, you see your changed state (Bundle Snapshot) of your class
//Because your bundle (i.e, the state of your class/activity) is the function of time.
En mi escenario, desde el fragmento de código justo arriba, veo que ha llamado a 375 métodos.
Nota: si hubiera agregado otro método dentro de onCreate () antes de imprimir todos sus métodos utilizando el fragmento de código anterior, también habría visto ese método. Significa que su estado de la clase (es decir, la instantánea) es según usted, lo que hace una y otra vez, sigue actualizando su instantánea.
La respuesta es tan simple como el ciclo de vida. Solo anule las devoluciones de llamada cuando necesite manejar cosas allí.
Android siempre llamará a cada devolución de llamada como se supone que lo haga, excepto en ciertas circunstancias.
El hecho de que no se garantice que se llamen a ciertas devoluciones de llamada no significa que sean inútiles. Simplemente no intentes manejar cosas sensibles en tales métodos de devolución de llamada.
Lo que personalmente creo que es el desarrollador debe dividir el trabajo en diferentes estados de la actividad. La secuencia del trabajo debe conservarse en este caso, lo que es más importante que pienso, y es por eso que Android no puede manejar un largo proceso de IU en un solo hilo y da error de que Android tiene "tanto trabajo por hacer" en Esta referencia puede ser causa de que se bloquee a veces. Por lo tanto, debemos evitar escribir todo el código en una sección. El código se escribiría en funciones o clases de diferencia y podemos derivar estas funciones según el requisito. Gracias.
onCreate () obviamente primero. Su actividad puede entonces entrar en Pausa (). A partir de ahí se puede onResume () o onDestroy (). Ese es el camino más simple a través del ciclo de vida que conozco.
Tuve una actividad que no tenía un método onPause (). A través de una serie de eventos impares, noté en DDMS que mi aplicación no estaba visible, pero todavía estaba solicitando freshAds de AdMob :) Buena batería. Eso ya se resolvió, pero me recordó lo importantes que son las cosas simples.