Actualización de GUI: Runnables vs Messages
Para actualizar la GUI de otros hilos, hay básicamente dos enfoques principales:
-
Utilice java.lang.Runnable con cualquiera de estos métodos:
- DialogFragment en Android con tema
- Android: ¿Cómo puedo navegar de un "detalle" a otro "detalle", mientras que el botón "Arriba" vuelve a la lista "Maestro"?
- Anular los colores del menú contextual en Android
- Creación de un diálogo de preferencias estándar de Android
- No se muestra ninguna imagen de fondo en Galaxy Nexus (SOLO)?
Activity.runOnUiThread(Runnable) View.post(Runnable) View.postDelayed(Runnable, long) Handler.post(Runnable)
-
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:
-
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), ...
-
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.
- ¿Cómo puedo desactivar todo el efecto de desplazamiento en mi aplicación?
- Simple AlarmManager ejemplo para disparar una actividad en 10 minutos
- Jerarquía de estilo en Android - ¿cuál es el orden de importancia?
- Android - Creación de listview con encabezados flotantes
- Dibujo de mapa de bits de mosaico con alineación inferior
- ¿Cómo detectar el movimiento de Google MapView en Android?
- Control deslizante en Android ... ¿SeekBar es realmente mi mejor / única opción?
- GetView vs. BindView en un CursorAdapter personalizado?
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.
- Progaurd issue "Advertencia: Ignorar el atributo InnerClasses para una clase interna anónima"
- Cómo se ejecuta una aplicación de Android en Dalvik Virtual Machine.