studio programacion herramientas fundamentos con avanzado aplicaciones android user-interface message runnable

android - programacion - Actualización de GUI: runnables vs mensajes



manual de android en pdf (4)

Para actualizar la GUI desde otros hilos, básicamente hay dos enfoques principales:

  1. Use java.lang.Runnable con cualquiera de estos métodos:

    Activity.runOnUiThread(Runnable) View.post(Runnable) View.postDelayed(Runnable, long) Handler.post(Runnable)

  2. Use android.os.Message:

    Handler.sendMessage(Message) / Handler.handleMessage(Message)

También puede usar AsyncTask, pero mi pregunta está más centrada en el caso de uso de actualizar un componente muy simple. Veamos cómo se haría usando ambos enfoques:

  1. Usando Runnables:

    TextViev tv = ...; final String data = "hello"; Runnable r = new Runnable() { @Override public void run(){ tv.setText(data); } }; //Now call Activity.runOnUiThread(r) or handler.post(r), ...

  2. Usando mensajes:

    Message m = handler.obtainMessage(UPDATE_TEXT_VIEW, "hello"); handler.sendMessage(m); //Now on handler implementation: @Override public void handleMessage(Message msg) { if(msg.what == UPDATE_TEXT_VIEW){ String s = (String) msg.obj; tv.setText(data); } ... //other IFs? }

En mi humilde opinión, los mensajes no son el camino a seguir porque:

  • No es fácil de entender para los nuevos programadores que no son Android (los enganches del manejador a su hilo durante la construcción).
  • La carga útil del objeto debe ser Parcellable si el mensaje cruza los límites del proceso.
  • Los mensajes se vuelven a usar (¿son propensos a errores si no se limpian adecuadamente?)
  • El controlador tiene un doble rol (envía mensajes, pero también los maneja)
  • Los atributos del mensaje son públicos, pero también ofrecen getter / setter.

Por otro lado, Runnables sigue el conocido patrón de comandos, y son más amigables con los programadores y legibles.

¿Cuáles son las ventajas de usar Messages over Runnables? ¿Los mensajes están en segundo plano en la programación de Android moderna? ¿Hay algo que puedas hacer con los mensajes que no se pueden hacer con ejecutables?

Gracias por adelantado.


Diría que hay poca diferencia entre usar un Message vs un Runnable . En general, se reducirá a las preferencias personales. ¿Por qué? Al mirar el código fuente, verá que publicar un Runnable usa el mismo mecanismo de mensajería. Simplemente conecta Runnable a un Message y lo envía.

4.4.2 Código fuente

public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }

Ref: Grep Code - Handler


Prefiero Runnable al Message . Creo que el código que usa Runnable es mucho más claro que Message , porque el código de manejo de eventos está muy cerca del evento. Además, puede evitar la sobrecarga de definir constantes e intercambiar casos.

Y no creo que el uso de Runnable viole la encapsulación. Puede extraer el código en Runnable.run() en otro método en la clase externa, por ejemplo on...Event() , o incluso envolverlo en un objeto EventHandler . Ambas formas son mucho más claras que el uso de Message , especialmente cuando se necesitan referencias de tienda en Message , porque el uso de Runnable evita msg.obj . Y el campo sin nombre msg.obj también es propenso a errores y, a veces, ineficiente de entender.

Y Runnable también puede reutilizarse almacenándolo como un campo.


Handler interfaz del Handler proporciona mucha más funcionalidad que runOnUiThread() , de acuerdo con los documentos:

Hay dos usos principales para un Manejador:
(1) para programar mensajes y ejecutables que se ejecutarán como un punto en el futuro
(2) para poner en cola una acción que se realizará en un hilo diferente al suyo.

runOnUiThread solo hace un subconjunto de (2). es decir, "poner en cola una acción que se realizará en el hilo de UI "

Así que IMO a menos que necesite esas características adicionales runOnUiThread es suficiente y preferida.


Messages se pueden reutilizar, por lo que se generan menos objetos creados y menos GC. También terminas con menos clases y tipos anónimos.

Una gran ventaja es que una clase que envía un Message a un Handler no necesita saber nada sobre la implementación de ese Message . Eso puede ayudar en la encapsulación dependiendo de dónde se usa.

Por último, considere la diferencia de limpieza entre

mHandler.obtainMessage(DO_STUFF, foo).sendToTarget();

vs

final Foo tempFoo = foo; mHandler.post(new Runnable(){ @Override public void run(){ doStuff(tempFoo); } };

Si tiene varios lugares en los que debería hacer doStuff() , el primero es MUCHO más legible y tendrá menos duplicación de código.