El que se este iniciando en esto de Android, ya sabe que el Activity viene a ser como una aplicación de formulario en Windows (salvando las distancias claro)… pues al igual que en una aplicación Windows, no se organiza todo en un solo form o como en este caso en un solo activity.
Siempre existe un Activity principal que dispara otros “Sub-Activity” y generalmente estos últimos nos deben devolver algún valor. Pues estos son los que vamos a ver, pero antes de empezar quiero pedir disculpas anticipadas a los gurús de Android ya que este mini tutorial lo escribo para afianzar lo que he aprendido hoy, y como todo el mundo sabe en esto de la programación, la experiencia la da el tiempo, por lo tanto con seguridad que tratare las cosas con cierta sencillez y dejando algunas cosas fuera del tintero por no terminar de comprenderlas.
Pues bien dicho esto comencemos a definir algunos conceptos:
- Intent: Digamos que son los sistemas que nos proporciona Android para invocar a un Activity. (buen artículo sobre los Intent en español)
- Bundle: es una estructura que permite almacenar datos (clave/valor) y pasarla de una actividad a otra, siempre de datos primitivos.
Bueno, sigamos preparándonos para una Sub-Actiity. La clase que vayamos a usar como subactivity la debemos crear en el mismo proyecto en el que estemos trabajando en un fichero diferente sobre el directorio src. Debe pertenecer al mismo paquete donde tenemos nuestro Activity principal. A continuación os dejo una captura de mi proyecto en eclipse (comento esto porque en los diferentes tutoriales que he ido encontrando nadie lo comentaba, y me hubiera ahorrado un tiempo si lo hubieran hecho).
Para terminar de preparar nuestro proyecto, debemos decirle al AndroidManifiest.xml que vamos a disponer de otro activity. Lo que hacemos es abrirlo y colocar la línea que marco en rojo.
Tened en cuenta que el atributo android:name debe coincidir con el nombre de la clase que hayáis definido. y el android:label, yo lo cojo del fichero que cuelga de values llamado strings.xml donde previamente he definido un ítem llamado “configuracion_name”.
ACTIVITY PRINCIPAL
Bien, vamos a comentar con el código que debemos usar en nuestra Activity principal. En mi caso lo que he hecho es que en una opción del menú de mi aplicación, llamo al sub-activity:
Intent i = new Intent(this,configuracion.class);
this.startActivityForResult(i, 0);
Como ya hemos dicho, el intent nos permite llamar a otro activity. El intent lo instanciamos pasándole el contexto en el que va a actuar (o sea la propia aplicación) y la clase que queremos llamar. La siguiente línea lo que indica es que el Activity se lanza esperando una respuesta con el intent que hemos creado y esperando que si todo va bien el código que nos devuelva sea 0. Si hubiéramos querido pasar alguna información al activity que vamos a llamar, deberíamos haber hecho algo como lo que sigue:
Bundle bund; //creamos el bunde
bund.putString(“clave01”,”valor para clave”); //definimos una clave y un valor para la misma.
i.putExtras(bund); //lo añadimos al intent
En el activity principal solo nos queda crear un evento que responda cuando el sub-activity finaliza. Debemos tener muy en cuenta que esto no funciona como formulario modales donde el flujo del programa se para… por ello es necesario controlar con un evento el funcionamiento del sub-activity. Bien, en nuestro activity principal creamos una función como esta:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0){
Bundle b = data.getExtras();
tv.setText(b.getString("ImagenSeleccionada"));
}
}
Básicamente lo que hacemos es comparar si lo que nos ha devuelto el sub-activity corresponde con el código que le hemos pasado al crearlo como que todo es ok. Si es así, creamos un bundle donde cargamos toda la información que nos hayan remitido y finalmente la muestro en un textview (en este caso muestro solo el valor cuya clave es ImagenSeleccionada).
SUB ACTIVITY
Bien, ahora pasamos a la clase (en mi caso llamada configuracion) que vamos a llamar desde la principal. A casi todos los efectos es una clase normal, igual que la principal, pero debemos controlar que esta devuelva lo necesario. En mi caso he creado una función a la que llamo cuando finalizo el trabajo con este Activity:
public void returnToCaller(View view){
Intent i;
i=new Intent();
i.putExtras(bund);
setResult(0,i);
finish();
}
Bien, analicemos esto, en primer lugar el intent.. necesitamos comunicarnos con el otro activity por lo tanto nos toca usarlo (sin embargo en este caso no le indicamos clase ninguna, es decir lo vamos a usar como transporte de los datos del bundle). Lo siguiente cargar en el intent los datos del bundle al cual le habremos cargado información en nuestra aplicación conforme nos haya hecho falta (hemos visto un ejemplo de como hacerlo antes). Y ahora lo más importante, el setResult donde el primer parámetro indica que todo ha ido bien (recordamos que en el ACtivity principal definimos que si el sub-activity devolvía 0 es porque todo había ido con normalidad) y el intent que contiene el bundle. Y como colofón el finish(); que se encarga de cerrar el Activity y pasar todo lo que teníamos preparado al Activity principal.
Para llamar a esa función, lo que yo he hecho ha sido crearme un botón y en el evento onClick le he asignado la función returnToCaller. Es por este motivo que he tenido que crear la función con un parámetro View, ya que cuando declaras funciones para eventos en el xml este por defecto siempre pasa como parámetro el View que lo dispara… y voila.. ya tenemos nuestro Activity con su SubActivity….
¿O no?.. veréis, estaba yo tan contento con que todo funcionaba, hasta que se me ocurre, estando en la pantalla de la clase de configuración, dar al botón Back …y de pronto ….la bonita pantalla de Android diciendo que ha ocurrido alguna cosa inesperada y que tiene que cerrarse. El motivo de esto es que hemos vuelto al Activity principal sin remitir los datos necesarios para el evento onActivityResult. Pues buscando un poco he visto como disparar nuestra función returnToCaller cuando se pulsa esta tecla:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0)
returnToCaller(null);
return true;
}
Ahora si, de esta forma ya podemos usar un formulario llamado desde otro formulario (en lenguaje windows XD) o mejor dicho, que un Activity dispare otro Activity.
Espero que os haya sido de ayuda…