Android: comunicación de hijo a padre

Este es un tutorial de algo que acabo de aprender, así que si encuentran algún error, estaré muy agradecida si me lo hacen ver :)

Esto es básicamente lo que haremos:

pre preview

Ya existe un tutorial que indica cómo enviar información desde una actividad hacia una actividad invocada, es fácil, sólamente tienes que adjuntar los datos en el intent que inicia la actividad. En este tutorial explico cómo enviar información desde la actividad invocada hacia la actividad invocadora, esto es un poco más difícil (especialmente porque la documentación del método finishActivity(requestCode) está un poco desatinada, y el tutorial oficial está incompleto).

TL;DR: finishActivity(requestCode) no finaliza la actividad, sólamente setea el request code con el que la actividad finalizará. Para realmente finalizar la aplicación, debes usar finish() después de haber usado finishactivity(…).

Piensa en una actividad invocada como una función que retorna información al finalizar. En el código del invocador añadiremos el método invocar que será ejecutado al hacer clic en el botón Invocar del view.

    // el argumento View es necesario cuando el método es invocado desde el view.
    public void invocar (View view) {
        startActivityForResult(new Intent(this, Invocado.class), PEDIDO_DE_MENSAJE);
    }

Luego en el invocado vamos a escribir el código del botón Enviar.

     public void enviar (View view) {
        Intent intento = getIntent();
        EditText recipienteNombre = (EditText) findViewById(R.id.nombre);
        EditText recipienteMensaje = (EditText) findViewById(R.id.mensaje);

        intento.putExtra("mensaje", recipienteMensaje.getText().toString()); // ewww
        intento.putExtra("nombre", recipienteNombre.getText().toString()); // eeewwwwww D'X

        // identifica la respuesta como exitosa.
        setResult(RESULT_OK, intento);
        // identifica el tipo de respuesta como respuesta a pedido de mensaje del invocador.
        finishActivity(Invocador.PEDIDO_DE_MENSAJE);
        // finaliza la actividad devolviendo la respuesta en el callback de quien la invocó.
        finish();
    }

Esas dos líneas que provocan asco no me gustan porque hacen que el código sea un spagetti DX. Pese a que el método putExtra tiene sobrecarga para todos los tipos primitivos de Java, imagina que queremos enviar un montón de datos, por cada dato un putExtra… por cada putExtra un nombre… ewwwwww DX (y si lo dejaramos así, se pondría peor! luego, al querer recibir el mensaje en el Invocador, tendríamos que recibir cada dato por su nombre x__x)

En lo personal prefiero enviar un objeto mediante el putExtra, para ello necesitamos crear la clase del objeto que queremos serializar, y que implemente la interfaz Serializable

    public class Mensaje implements Serializable {
        public String contenido;
        public String remitente;

        public Mensaje (String contenido, String remitente) {
            this.contenido = contenido; this.remitente = remitente;
        }

        public String toString () {
            return "[" + remitente + "]: " + contenido;
        }
    }

Por lo que en vez de esas dos asquerosas líneas de código, tendremos esta apetitosa línea de código

    // apetitosa linea de código que envía elegantemente los datos XD
    intento.putExtra("mensaje", new Mensaje(recipienteMensaje.getText().toString(),
        recipienteNombre.getText().toString()));

Ahora recibiremos los datos desde el Invocador. Cuando una actividad finaliza con un código de request, dispara un evento que es recibido por el AppCompatActivity que lo invocó mediante el método onActivityResult.

Este evento es disparado independientemente del tipo de request, o de que el resultado de la actividad haya fracasado o tenido éxito. Por lo que debemos verificar nosotros mismos el éxito de la actividad, y verificar si el pedido del mensaje es el deseado.

    final static int PEDIDO_DE_MENSAJE = 1;

    // ...

    @Override
    public void onActivityResult (int pedido, int resultado, Intent datos) {
        if (pedido == PEDIDO_DE_MENSAJE) { // tanto pedido como PEDIDO_DE_MENSAJE son numeritos
            // pero es buena práctica ponerle nombre a estos numeritos en vez de llamarlos
            // por su numerito XD
            if (resultado == RESULT_OK) {
                TextView recipiente = (TextView) findViewById(R.id.recibido);

                // apetitosa linea de código que recibe elegantemente los datos XD
                Mensaje recibido = (Mensaje) datos.getSerializableExtra("mensaje"); 

                recipiente.setText("[" + recibido.remitente + "]: " + recibido.contenido);
            }
        }
    }

 

Advertisements