Actualización de GUI: Runnables vs Messages

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

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

    Activity.runOnUiThread(Runnable) View.post(Runnable) View.postDelayed(Runnable, long) Handler.post(Runnable) 
  2. Usar android.os.Message:

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

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

  1. Uso de 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. Uso de 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? } 

IMHO, los mensajes no son el camino a seguir porque:

  • No es fácil de entender para los nuevos programadores no-androides (ganchos del manipulador 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 reutilizan (¿propensos a errores si no se limpian correctamente?)
  • El manejador tiene una función dual (envía mensajes, pero también los maneja)
  • Los atributos de mensaje son públicos, pero también ofrecen getter / setter.

Por otra parte, Runnables sigue el patrón de comando bien conocido, y es más programable-amistoso y legible.

Entonces, ¿cuáles son las ventajas de usar mensajes sobre Runnables? ¿Son los mensajes empujados al fondo en la programación moderna de Android? ¿Hay algo que puedas hacer con mensajes que no se pueden hacer con Runnables?

Gracias por adelantado.

Yo diría que hay poca diferencia entre el uso de un Message vs un Runnable . En su mayoría se reduce a la preferencia personal. ¿Por qué? En cuanto al código fuente, verá que publicar un Runnable utiliza el mismo mecanismo exacto de mensajería. Simplemente adjunta el 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: Código Grep – Manejador

Messages pueden ser reutilizados, por lo que resulta en menos objetos creados y menos GC. También terminan 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 acerca de la implementación de ese Message . Eso puede ayudar en la encapsulación dependiendo de donde se utiliza.

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 tienes varios lugares donde tendrías que doStuff() , el primero es MUCHO más legible y tendrás menos duplicación de código.

Handler proporciona mucha más funcionalidad que runOnUiThread() , según docs:

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 enquear una acción que se realizará en un hilo diferente que el suyo propio.

runOnUiThread hace sólo un subconjunto de (2). Es decir, "enqueue una acción a realizar en el subproceso de UI "

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

Prefiero Runnable al Message . Creo que el código que utiliza 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 y cambiar casos.

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

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

  • Mostrar tostada compleja de BroadcastReceiver
  • El uso de SearchView con AppCompatActivity genera fallas en la interfaz de usuario
  • "Error al registrar el canal de entrada" - ¿qué causa esto y cómo solucionarlo?
  • Estilo oficial de la semana del despertador oficial de Android
  • Cómo establecer un tema diferente en un diseño
  • La forma más rápida de obtener la entrada del usuario en Android
  • Cómo crear GUI en Android en lugar de utilizar XML?
  • Android: Colaboración de la interfaz de usuario (Jenkins + Spoon +?)
  • Cómo centrar el icono y el texto en un botón android con el ancho establecido en "fill parent"
  • ¿Cómo alinear vistas en la parte inferior de la pantalla?
  • ¿Cómo hacer segmentar seekbar / slider parecen seguir?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.