- ¿Cuantas veces te has encontrado que necesitas entregar un resultado de una
Activity
a otra? - Muchas, no recuerdo ninguna aplicación donde no lo haya tenido que hacer.
- ¿Te resultó difícil? ¿Como lo hiciste?
- No, de hecho fue muy fácil, Android siempre ha tenido un método
startActivityForResult(Intent, int)
para lanzar unaActivity
de la que esperas un resultado y otro métodoonActivityResult(int, int, Intent)
para recibirlo, no tiene ningún misterio. - Bien ¿y que pasa si hay más de una
Activity
implicada en el proceso? - Ah, también es muy fácil, cuando lanzas la segunda
Activity
implicada en el flow lo haces añadiendo el flagIntent.FLAG_ACTIVITY_FORWARD_RESULT
alIntent
y entonces será tu siguienteActivity
la encargada de llamar asetResult
para entregar el resultado. - ¿Eso es todo?
- Bueno, en realidad no, en realidad tienes que hacer un
Activity.finish
de la primeraActivity
del flow porque sino cuando el usuario termine la segunda, volverá a la primera y tendrá que salir manualmente de esta para recibir el resultado. - Mmmm... ¿eso no es muy elegante no?
- Bueno, puedes llamar a
Activity.finish
como he dicho antes, de esta forma cuando el usuario termina en la segundaActivity
, va directamente a la que está esperando el resultado. - ¿Y que pasa si el usuario pulsa
back
cuando está al final del flow? - Que se sale del flow.
- Pero entonces pierde toda la información que tenía entre medias ¿no?
- Si.
- ¿Y si en lugar de tener un flow de 2 actividades tienes un flow de 5 o 6 o incluso de 10?
- Pues el usuario tendría que comenzar el flow desde el principio.
- Bien, ahí es donde quería llegar, yo también me he enfrentado a este problema y de momento, esta es la solución que mas me hag gustado.
¿Como hacerlo?
Esto es bastante sencillo de conseguir y lo más importante, con poco código:- Primero necesitamos lanzar la primera
Activity
del flow constartActivityForResult
:
Intent intent = new Intent(this, ProfileNameStepActivity.class); startActivityForResult(intent, PROFILE_REQUEST_CODE_FLOW);
- Y esperamos el resultado como hariamos si el flow tuviese una sola
Activity
.
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PROFILE_REQUEST_CODE_FLOW && resultCode == RESULT_OK) { Profile profile = ExtrasUtils.getProfile(data); onProfileCompleted(profile); } else { super.onActivityResult(requestCode, resultCode, data); } }
- También en la última
Activity
del flow añadiremos:
Intent intent = new Intent(); intent.putExtra(ExtrasUtils.EXTRA_PROFILE, new Profile.Builder().withName(name).withAddress(address).build()); setResult(RESULT_OK, intent); finish();
De momento no hemos hecho nada especial, esté código lo hemos escrito cientos de veces cada vez que lanzamos unaActivity
esperando un resultado de ella.Esta es la parte interesante...- Ahora lanzamos el resto de actividades del flow con
startActivityForResult
también, aunque en este caso elrequestCode
no es importante ya que no esperamos su resultado:
/* Podemos pasar cualquier número como request code aquí porque no lo escucharémos (a no ser que queramos lanzar un sub-flow, después explico que sería un sub-flow y como incluirlo) */ Intent intent = new Intent(this, ProfileFinalStepActivity.class); startActivityForResult(intent, 0);
- Finalmente necesitamos esta pieza de código en nuestra
BaseActivity
de la cual heredan todas nuestras actividades.
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { setResult(resultCode, data); finish(); } }
Esta última parte de código, es la que realmente hace la magia. Si te fijas, como hemos lanzado todas nuestras actividades constartActivityForResult
, cuando estas terminen laActivity
anterior será llamada enonActivityResult
, y lo que estamos haciendo es comprobar si laActivity
de la que viene ha añadido el resultado ya, si lo ha hecho, pasamos el resultado a laActivity
anterior y esto se hará progresivamente hasta que algunaActivity
haya sobreescrito el métodoonActivityResult
y esté actualmente esperando por elrequestCode
.Está misma técnica puede ser utilizada para incluir sub-flows dentro de un flow, imagina por ejemplo que tu aplicación permite al usuario realizar compras y que para realizar esa compra el usuario tiene que proveer alguna información básica como el nombre y la dirección (o un perfil entero).El mismo código que hemos utilizado para empezar/acabar un flow, podemos incluirlo en cualquier paso del flow para añadir un sub-flow y funcionará exactamente igual.¿Que hemos conseguido con esto?
- Ser capaz de empezar y acabar un flow en el mismo sitio.
- Entregar el resultado de un flow (grupo de actividades) de una forma sencilla.
- Posibilidad de añadir flows adicionales dentro del flow.
9 de abril de 2016
Android - Flow result en lugar de Activity result o como obtener un resultado entre actividades
Etiquetas:
Activity,
Activity Result,
Android,
Development,
FLAG_ACTIVITY_FORWARD_RESULT,
Flow,
Flow Result,
onActivityResult,
Result,
startActivityForResult
Suscribirse a:
Enviar comentarios (Atom)
No hay comentarios:
Publicar un comentario