El ciclo de vida de una Activity en Android

Android tiene una forma peculiar de gestionar las aplicaciones que choca un poco con los sistemas operativos tradicionales. Pese a estar montado en un linux con el kernel 2.6, Android no tiene por costumbre matar las aplicaciones cuando las cerramos. La clave está en que igual lo hace o igual no, según las necesidades o lo que Android considere oportuno. La cosa es que no hay que empeñarse en tener un botón para matar la aplicación, oficialmente no se recomienda y se todo se resume a un tranqui, Android se preocupa.

Como usuario habitual de linux y gran devoto de Nuestra Señora del kill -9 esto de no poder MATAR procesos (o siendo precisos mandar la señal de la muerte SIGKILL) es algo que no me gusta pero... lo han diseñado así y parece que el nuevo windows va por el mismo camino. Como decían unos MVP a los que vi tiempo atrás: "Windows Vista no chupa recursos, lo que hace es... aprovecharlos" con un par. Así que la idea es barra libre, todos los programas abiertos y si nos quedamos sin nada ya iremos matando. La idea no es mala del todo ya que en teoría mantienes todo abierto y no hay que esperar a que los programas se abran y eso es coherente con la forma de usar el móvil en la que saltas de una pantalla a otra y puedes ser interrumpido por llamadas.

Los estados
LifeCycle de android

Estos son los estados por los que puede pasar una aplicación en Android:

  • onCreate: es el primer método en ser ejecutado por la Activity una única vez hasta que se destruye.
  • onStart: se ejecuta inmediatamente después de onCreate u onRestart, y es previo a la visualización de la pantalla.
  • onResume: se ejecuta inmediatemente después de onStart u onPause, la actividad se muestra al usuario y esta pasa a primer plano.
  • onPause:se invoca previamente al Stop cuando la actividad sale del primer plano. Aquí es donde se suele aprovechar para salvaguardar datos. Podemos distinguir si la aplicación va a pausarse o a terminarse.
  • onStop: tras la pausa puede venir el stop. Aquí se liberan recursos, OJO si andamos por ejemplo con SQLite ya que el Stop se carga los cursores.
  • onRestart: volvemos al start y se puede ejecutar desde el estado de Stop.
  • onDestroy: simétrico del create, cuando la aplicación se destruye definitivamente por Android.
El trauma del cambio de orientación de pantalla

Al cambiar de orientación la pantalla, algo que al usuario le parece una pijada, para la App estás provocando un verdadero terremoto. La aplicación salva su estado (si sobrescribes ese método) se pausa (pause), se para (stop), se destruye (destroy), se crea (create) otra vez, se inicia (start) y se recuperan los valores salvados anteriormente. Si estás con el emulador tienes puedes hacer Ctrl-F12 para hacer cambios de orientación. Ojo, el dispositivo debe soportarle y si no lo tiene lo debes agregar en sus opciones de hardware.

Probando el ciclo de vida

Esta es un App para obvservar el ciclo de vida. En su día ya la hice pero esta es algo más decente, es la clásica Activity y sobreescribe todos los handlers vinculados al ciclo de vida de una App de android. Y de paso también prueba el tema de guardar contenidos un Bundle (lo que viene a ser un saco para guardar el estado de la aplicación), que luego se pueden recuperar en el Create. La aplicación hay que probarla con el DDMS ya que lo único que hace es mandar mensajes al logcat. Probándolo en un 2.2 y un 4.0 me ha chocado que el botón Back para la App y finalmente Android destruye la App. En cambio con el Home siempre se pausa y sí que activa el método para guardar el estado. En un Activity se supone que hacer un this.finish es equivalente al botón Back, pero como decía no hay un botón de matar. A través de la configuración de Android, dentro de aplicaciones sí que tenemos un botón para matar y cargarnos la memoria que esté utilizando cualquier App.

package info.pello.android.lifecycle;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;

/**
 * Simple Activity to observe Android App lifecycle.
 * @author Pello Xabier Altadill Izura
 * @greetz 4 u as always
 */
public class MainActivity extends Activity {
	
	private static int counter = 0;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		log("App created");
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		if (null != savedInstanceState) {
			Log.d("Restored value1: " + savedInstanceState.getString("Something") , "PELLODEBUG");
			Log.d("Restored value2: " + savedInstanceState.getString("Another") , "PELLODEBUG");
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		log("Options menu created");
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	/**
	 * called from the button and tells Android that 
	 * this should be closed.
	 * @param v
	 */
	public void stopApp (View v) {
		this.finish();
	}

	/**
	 * Suposed to be called when restoring app when:
	 * 1. Screen orientation changes
	 * 2. App was killed by android
	 * But:
	 *     "Most implementations will simply use onCreate(Bundle) to restore their state, but it is sometimes convenient to do it here after all of the initialization has been done or to allow subclasses to decide whether to use your default implementation. The default implementation of this method performs a restore of any view state that had previously been frozen by onSaveInstanceState(Bundle)."
	 * There is no reason to override onRestoreInstanceState() unless you are subclassing Activity and it is expected that someone will subclass your subclass. 
	 * @param bundle data to restore app state
	 */
	@Override
	protected void onRestoreInstanceState(Bundle bundle) {
		super.onRestoreInstanceState(bundle);
		log("Restoring Instance State");
		Log.d("Restored value1: " + bundle.getString("Something") , "PELLODEBUG");
		Log.d("Restored value2: " + bundle.getString("Another") , "PELLODEBUG");
	} 

	/**
	 * when user press home button this is
	 * called before app is paused
	 */
	@Override
	protected void onSaveInstanceState(Bundle bundle) {
		super.onSaveInstanceState(bundle);
		// Save some values AFTER!! invoking super method
		bundle.putString("Something", "Saved for later");
		bundle.putString("Another", "Another Saved for later");
		log("Saving instance State...");
	} 

	/**
	 * called after the app is Created
	 * or after stop > restart
	 */
	@Override
	protected void onStart () {
		super.onStart();
		log("App Started");
	}
	
	/**
	 * called when app is resumed (from paused) and also
	 * the first time is executed (after start)
	 */
	@Override
	protected void onResume () {
		super.onResume();
		log("App Resumed");
	}
	
	/**
	 * called when app is paused
	 */
	@Override
	protected void onPause () {
		super.onPause();
		// We can control if the App is about to finish
		if (this.isFinishing()) {
			log("App is finishing");
		} else {
			log("App is NOT finishing");
		}
		
		log("App paused");
	}
	
	/**
	 * called when app is restarted from stop state
	 */
	@Override
	protected void onRestart () {
		super.onRestart();
		log("App Restarted");
	}
	
	/**
	 * called when app is stoped
	 */
	@Override
	protected void onStop () {
		super.onStop();
		log("App Stopped");
	}
	
	/**
	 * called when app is stoped is destroyed by Android
	 */
	@Override
	protected void onDestroy () {
		super.onDestroy();
		log("APP DESTROYED");
	}
	
	/**
	 * logs messages using Android log
	 * @param msg
	 */
	private void log (String msg) {
		Log.d("LifeCycle["+(counter++)+"]> "+msg,"PELLODEBUG");
	}
}

by Pello Altadill 08/15/2013 13:55:06 - 514 hits

Callbacks y funciones asíncronas, el estilo Node.js

El estilo nodejs Yo pensaba que sabía -algo- de javascript hasta que descubrí Node.js :P. En fin, espero ser siempre un aprendiz. Conforme te vas asomando a nuevas tecnologías tratas de hacer las cosas correctamente y como recién llegado aplicas lo de donde fueres haz lo que vieres. ¿Existe algún documento con las convenciones de Node.js? Sí, Node.js tiene una guía de estilo aunque no e...

by Pello Altadill 08/14/2013 22:08:41 - 545 hits

More »

Intents con parámetros y startActivityForResult

Cuando en Android queremos abrir una nueva pantalla o Activity se hace de una manera muy curiosa: se crea un Intent. Los Intent son eso, intentos. No garantizan que el resultado vaya a ser el correcto ni si quiera que alguien vaya a responder, y es que los intents se pueden usar tanto para abrir Activities como para solicitar cualquier cosa (iniciar una llamada, mandar un mensaje, etc... ). Con los intents en definitiva se llama a componentes de cualquier tipo. Pueden ser internos de la propia a...

by Pello Altadill 08/14/2013 12:57:24 - 373 hits

More »

Ejemplo de IndexedDB la BD de HTML5

HTML5 trae un montón de nuevas posibilidades al navegador. Se ha hablado mucho del formato de vídeo, del canvas, los websockets, de los nuevos controles de formulario pero a mí en particular me ha interesado especialmente aquello de una BD en el cliente. Es un tema que no está tan documentado como el resto y que en muchos libros de HTML5 o ni se menciona o se hace de pasada. Y lo que es peor, hay información en blogs pero a nada que esté desfasada los ejemplos no funcionan como la llamada a...

by Pello Altadill 08/13/2013 22:35:53 - 904 hits

More »

Eventos en nodejs

NodeJS está orientado a eventos por tanto disponer de mecanismos para definir nuestros propios eventos es algo fundamental. Como vamos a ver no tenemos más que importar el módulo events y a partir de ahí ya podremos trabajar con instancias de EventEmitter. Y como disponemos de herencia, podemos agregar la emisión de eventos a nuestras clases. Un ejemplo sencillo de eventos Este programa lee datos por consola y puede generar tres eventos Si el usuario escribe algo S...

by Pello Altadill 08/13/2013 10:37:21 - 215 hits

More »

Consejos para programar Android

Desarrollar aplicaciones para Android no es tan ágil como con otras tecnologías. Montar la aplicación configurando cada uno de los ficheros XML (cosa que está bien pensada y tal) es un poco pesado y lo peor es que cuando lo quieres probar para ver el resultado tienes que esperar mucho y encima lo más seguro es que casque y que la aplicación se pare de forma inesperada. Voy a dejar aquí algunos consejillos que espero resulten útiles. ...

by Pello Altadill 08/13/2013 09:40:38 - 505 hits

More »

Hibernate self join con XML

El hecho de echar un ojo a SGBD noSQL no significa que lo relacional esté proscrito, por eso hay que seguir investigando más escenarios de hibernate. Existen situaciones en las que una tabla o entidad se hace referencia a sí misma. El ejemplo típico es el de empleado con un campo idjefe que hace referencia a otro empleado. Otro mítico se da en los foros, donde un mensaje puede tener un id de mensaje padre. Siguiendo con nuestro ejemplo del ERP vamos a ver cómo apañar el mapeo a si mismo con la ta...

by Pello Altadill 08/12/2013 14:26:02 - 304 hits

More »

Almacenamiento local en HTML5

Local Storage Los navegadores modernos van disfrutando de nuevas capacidades impulsadas por HTML5. Una de las más llamativas es la posibilidad del almacenamiento local, en el cliente, que viene en dos formas: por un lado en dos arrays relacionales que nos permiten guardar datos con un límite supuesto de 5Mb (al estilo del $_SESSION de php pero en el cliente) y por otra parte la posibilidad de tener una base de datos en el cliente. Está última, que un principio parecía iba a ser SQLite fina...

by Pello Altadill 08/11/2013 22:51:12 - 259 hits

More »

Leyendo por consola y herencia en nodejs

Para poder hacer cosas básicas en la consola con node tenemos un objeto predefinido llamado process que nos provee de todo los necesario, desde jugar con la stdin, stdout, stderr hasta terminar la ejecución. En un alarde de originalidad, aquí tienes una calculadora muy simple en la que se deben introducir dos números y un operador. /** * calc.js * Trying to code the good ol' calc with node event driven way * @author Pello Xabier Altadill Izura * @greetz for you *...

by Pello Altadill 08/11/2013 00:17:05 - 329 hits

More »