Android: ¿Cuándo debo usar un controlador () y cuándo debo usar un hilo?

129

Cuando necesito que algo se ejecute de forma asincrónica , como una tarea de larga ejecución o una lógica que utiliza la red, o por cualquier razón, iniciar un nuevo subproceso y ejecutarlo funciona bien. La creación de un Handler y funcionando funciona así. ¿Cual es la diferencia? ¿Cuándo debo usar cada uno? ¿Cuáles son las ventajas / razones para usar ay Handlerno a Thread?

PD. - Por el bien de esta pregunta, ignoremos AsyncTask. - El Handler().postDelayedcaso de uso está claro para mí, por el bien de esta pregunta, supongamos que necesito que la tarea comience de inmediato.

JRun
fuente
En su situación, simplemente siga adelante y use un nuevo hilo, mi siguiente sugerencia sería AsyncTask, pero eso no es lo que quiere claramente. Los controladores se utilizan principalmente si desea agregar un retraso u otro tipo de personalización a un ejecutable.
kabuto178
1
@ kabuto178 bueno, hay otros beneficios de los controladores que vale la pena mencionar que omitiste. Tales como, ser capaz de interactuar con el hilo de interfaz de usuario a partir de un hilo separado ..
tony9099

Respuestas:

168

Si lo que está haciendo es "pesado", debería hacerlo en un hilo. Si no lo inicia explícitamente en su propio subproceso, se ejecutará en el subproceso principal (UI) que puede ser notorio como nervioso o lento para responder a la interfaz de sus usuarios.

Curiosamente, cuando está utilizando un hilo, a menudo es útil usar también un controlador como medio de comunicación entre el hilo de trabajo que está iniciando y el hilo principal.

Una interacción típica de Thread / Handler podría verse así:

Handler h = new Handler(){
    @Override
    public void handleMessage(Message msg){
        if(msg.what == 0){
            updateUI();
        }else{
            showErrorDialog();
        }
    }
};

Thread t = new Thread() {
    @Override
    public void run(){
        doSomeWork();
        if(succeed){
            //we can't update the UI from here so we'll signal our handler and it will do it for us.
            h.sendEmptyMessage(0);
        }else{
            h.sendEmptyMessage(1);
        }
    }   
};

Sin embargo, en general, la conclusión es que debe usar un subproceso cada vez que realice un trabajo que podría ser de larga duración o muy intenso (es decir, cualquier red, archivo IO, aritmética pesada, etc.).

FoamyGuy
fuente
¡Gracias por la rápida respuesta y la cantidad de tiempo invertido (y la velocidad de su respuesta!)! Entonces, déjame ver si obtuve esto: ¿El controlador está diseñado para facilitar la comunicación sin bloqueo entre los hilos de los trabajadores y el hilo de la interfaz de usuario?
JRun
3
@JRun Ese es uno de los usos, sí. Consulte la descripción del controlador en los documentos de Java para obtener información excelente al respecto. Incluyendo otro de sus usos (para programar mensajes y ejecutables que se ejecutarán en algún momento en el futuro).
FoamyGuy
Bien explicado @FoamyGuy!
tony9099
Hola, ¿está garantizado que updateUI()se ejecutará después onCreateView(después de cargar nuevas vistas)?
Zyoo
1
¿Por qué es message.what()? ¿No sería así if(msg == 0){? ¡Muchas gracias! :)
Ruchir Baronia
64

Handler y Thread son realmente 2 cosas diferentes.

Se debe crear un hilo para ejecutar trabajos de larga ejecución.

Un controlador es un objeto muy conveniente para comunicarse entre 2 subprocesos (por ejemplo: un subproceso en segundo plano necesita actualizar la interfaz de usuario. Puede usar un controlador para publicar algunos Runnable de su subproceso en segundo plano en el subproceso de la interfaz de usuario).

Por lo tanto, no puede elegir entre Handler o Thread. ¡Usa un hilo para hacer trabajos pesados! (puede usar un controlador si su subproceso en segundo plano activará algún trabajo en otro subproceso, la mayoría de las veces el subproceso de la interfaz de usuario)

ben75
fuente
¡Gracias por la rápida respuesta y la cantidad de tiempo invertido (y la velocidad de su respuesta!)!
JRun
28

Handlery Threadson dos cosas diferentes, pero no se contradicen entre sí. Puede tener a Handlery Threada al mismo tiempo y en realidad cada uno Handlerdebe ejecutarse en a Thread.

Para más detalles, puede consultar este artículo .

ingrese la descripción de la imagen aquí

pierrotlefou
fuente
19

A se Handlerejecuta en el mismo Thread, a se Threadejecuta en un hilo diferente.

Use un controlador si necesita ejecutar algo en el mismo hilo , generalmente un elemento GUI o algo así.

Use un hilo si desea mantener el hilo principal libre para hacer otras cosas . Use esto para cualquier cosa que tome una cantidad significativa de tiempo.

PearsonArtPhoto
fuente
66
¿Por qué debería usar un controlador si quiero ejecutar algo en el mismo hilo? ¿Cuál es el propósito del método mHandler.post (...)?
Elias
1
Elias, en tal caso, puede usar el controlador si desea que una determinada tarea se ejecute después de un cierto período de tiempo, o para repetir una tarea cada X veces. Si no quieres usar estas cosas, tienes razón. No es digno de utilizar un controlador. simplemente puede hacer las cosas de la GUI allí mismo, porque de todos modos está en el hilo de la interfaz de usuario, porque el controlador se ejecuta en el hilo en el que se creó.
tony9099
14

Los controladores son la mejor forma de comunicación entre el fondo y el hilo de la interfaz de usuario. En general, los controladores están asociados con la cola de mensajes de un subproceso y se utilizan para enviar mensajes y pueden ejecutarse en el mensaje.

UTILIZAR:

Subproceso: para realizar tareas en subproceso saperate (fondo) que subproceso de interfaz de usuario. (ayuda a desbloquear el hilo de la interfaz de usuario)

Controlador Se utiliza para comunicarse entre la interfaz de usuario y el subproceso en segundo plano.

Echa un vistazo a este artículo

Saubhagya Ranjan Das
fuente
4

Si necesita actualizar la interfaz de usuario desde un nuevo subproceso, debe sincronizar con el subproceso de la interfaz de usuario.

Puede usar la clase android.os.Handler o la clase AsyncTasks para esto.

La clase Handler puede actualizar la interfaz de usuario. Un controlador proporciona métodos para recibir instancias de la clase Message o Runnable.

Su hilo puede publicar mensajes a través del método sendMessage (mensaje msg) o mediante el método sendEmptyMessage ().

... más información aquí sobre subprocesos, etc. (incluye turnos para los diferentes mecanismos de subprocesamiento y sincronización y cuándo usar qué)

Beachwalker
fuente
Gracias por tomarse el tiempo para responder a mi pregunta. Me encanta el blog de Lars Vogel, es muy perspicaz y fácil de seguir. ¡Gracias!
JRun
2

¿Cuáles son las ventajas / razones para usar un controlador y no un hilo?

Un controlador le permite enviar y procesar mensajes y Runnableobjetos asociados con un hilo MessageQueue. Cada Handlerinstancia está asociada con un solo hilo y la cola de mensajes de ese hilo.

Cuando creas un nuevo Handler , está vinculado a la cola de hilo / mensaje del hilo que lo está creando; a partir de ese momento, enviará mensajes y ejecutables a esa cola de mensajes y los ejecutará a medida que salgan de la cola de mensajes. .

Hay dos usos principales para un controlador:

  1. Para programar mensajes y Runnables para que se ejecuten en algún momento en el futuro
  2. Para poner en cola una acción que se realizará en un hilo diferente al suyo.

Si usa hilos Java, debe manejar algunas cosas por su cuenta: sincronizar con el hilo principal, cancelar un hilo, etc.

Este subproceso único no crea un grupo de subprocesos a menos que use ThreadPoolExecutoro ExecutorServiceAPI.

(Tomó esta consulta de sus comentarios sobre la respuesta de Blackbelt)

¿Por qué no usar un ejecutor? e incluso si quisiera usar un controlador para hacer eso, ¿cómo?

Referencia: artículo sobre rendimiento de subprocesos

Hay ciertos tipos de trabajo que pueden reducirse a tareas altamente paralelas y distribuidas. Con el gran volumen de paquetes de trabajo que esto crea, AsyncTasky HandlerThreadno son clases apropiadas. La naturaleza de un solo subproceso AsyncTaskconvertiría todo el trabajo combinado en un sistema lineal. El uso de la HandlerThreadclase, por otro lado, requeriría que el programador gestione manualmente el equilibrio de carga entre un grupo de subprocesos.

ThreadPoolExecutor es una clase auxiliar para facilitar este proceso. Esta clase gestiona la creación de un grupo de subprocesos, establece sus prioridades y gestiona cómo se distribuye el trabajo entre esos subprocesos. A medida que la carga de trabajo aumenta o disminuye, la clase gira o destruye más hilos para ajustarse a la carga de trabajo.

 BlockingQueue workQueue= new LinkedBlockingQueue<Runnable>(100); // Work pool size
 ThreadPoolExecutor executor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),       // Initial pool size
            Runtime.getRuntime().availableProcessors(),       // Max pool size
            1, // KEEP_ALIVE_TIME
            TimeUnit.SECONDS, //  KEEP_ALIVE_TIME_UNIT
            workQueue);

Puede consultar este artículo de la guía del desarrollador en create-threadpool para obtener más detalles.

Eche un vistazo a esta publicación para Handlerusarla para ejecutar varias instancias Runnable. En este caso, todas las Runnabletareas se ejecutarán en un solo subproceso.

Android: tostadas en un hilo

Ravindra babu
fuente
1

Handlerse puede usar junto con Threadpara crear un mecanismo en cola. Puedes usar el handlerpara publicar algo en elThread Looper

Cinta negra
fuente
Gracias por tomarse el tiempo para responder a mi pregunta. ¿Por qué no usar un ejecutor? e incluso si quisiera usar un controlador para hacer eso, ¿cómo?
JRun
ejecutor es un poco diferente. Para usarlo, debe extender el subproceso y, en la ejecución, llamar al static.metohd prepare.of de la clase Looper. después de llamar al método estático bucle se crea una cola y se puede usar una orden handlerbin a requestes hacia adelante y obtener los resultados de vuelta
Blackbelt