2012-09-27 20 views
37

Me he encontrado con los conceptos Handlers y runOnUiThread. Pero para mí todavía parece ser una duda en cuanto a qué hechos difieren exactamente.¿Por qué utilizar Handlers mientras runOnUiThread hace lo mismo?

Ambos están destinados a realizar acciones de IU desde un hilo de fondo. Pero, ¿cuáles son los factores que deben considerarse al elegir entre los dos métodos?

Por ejemplo, considere un RunnableThread que realiza un servicio web en segundo plano y ahora quiero actualizar la interfaz de usuario.

¿Cuál sería la mejor manera de actualizar mi UI? ¿Debo ir por Handler o runOnUiThread?

Todavía sé que podría usar un AsyncTask y hacer uso de onPostExecute. Pero solo quiero saber la diferencia.

+2

'runOnUiThread' es solo un atajo para publicar un' Runnable' en un 'Handler'. 'Handler' es la base de cada recurso (?) De comunicación entre hilos definido por Android (por ejemplo' 'onPostExecute' de AsyncTask' utiliza un' Handler' para entregar el resultado de 'doInBackground'). – zapl

Respuesta

63

Activity.runOnUiThread() es un caso especial del más genérico Handlers. Con Handler puede crear su propia consulta de evento dentro de su propio hilo. El uso de Handlers instanciado con default constructorno significa significa que "código se ejecutará en el subproceso UI" en general. De forma predeterminada, los controladores enlazaron al Thread desde el que se crearon las instancias.

Para crear Handler que está garantizado para unirse a la interfaz de usuario (principal) de rosca debe crear Handler objeto binded a principal Looper así:

Handler mHandler = new Handler(Looper.getMainLooper()); 

Por otra parte, si se comprueba la aplicación de runOnuiThread() método, que está utilizando Handler de hacer las cosas:

public final void runOnUiThread(Runnable action) { 
     if (Thread.currentThread() != mUiThread) { 
      mHandler.post(action); 
     } else { 
      action.run(); 
     } 
    } 

Como se puede ver en el fragmento de código anterior, Runnable action habrá exe ejecutado inmediatamente, si se llama runOnUiThread() desde el subproceso UI. De lo contrario, lo publicará en Handler, que se ejecutará en algún momento posterior.

+0

, pero no "Subproceso del que se crearon las instancias". generalmente el hilo de la interfaz de usuario? –

+8

@Mike, esto depende totalmente de su código. A menudo sí, los manejadores se crean instancias del hilo principal, pero hay muchos casos en los que el desarrollador no tiene información exacta sobre el hilo actual al crear la instancia 'Handler'. Por lo tanto, el desarrollador debe usar 'new Handler (Looper.getMainLooper())' si necesita garantías que el manejador ejecutará en el hilo principal. – HitOdessit

+0

tengo gracias, eso es muy útil. –

0

Los manejadores eran la forma antigua (Nivel API 1) de hacer cosas, y luego se introdujeron AsycTask (Nivel API 3), junto con un mayor enfoque en usar runOnUIThread (Nivel API 1). Debe evitar usar manipuladores tanto como sea posible, y prefiere los otros dos según su necesidad.

+1

¿Pero por qué? Necesito la diferencia exactamente. ¿Puedes por favor explicar más? –

+0

No hay diferencia, puede lograr las mismas cosas con Handlers y Loopers, pero estas técnicas lo ayudan a evitar errores. Consulte http://en.wikipedia.org/wiki/Syntactic_sugar – Animesh

1

Handler tiene muchos trabajan como paso de mensajes y actualización de la interfaz de usuario frecuente si se inicia un hilo para cualquier ejecución de una tarea .A Handler le permite enviar y Mensaje de procesos y objetos asociados a Runnable MessageQueue de un hilo ,, que es muy útil en muchas aplicaciones como el chat bluetooth wifi ,, el chat ... y manipulador tiene como Método PostDelay y PostAtTime por el cual se puede jugar en cualquier vista para animar y visibilidad cambio y así sucesivamente

usted debe mirar en este

http://developer.android.com/guide/components/processes-and-threads.html

http://developer.android.com/tools/testing/activity_testing.html

+0

Sí, pero ¿por qué no utilizar runOnUIThread aquí? –

+1

runOnUIThread siempre realiza el cálculo en el subproceso UI, mientras usa el controlador U puede disparar un subproceso para realizar cálculos pesados ​​allí y publicar el resultado en el subproceso de la interfaz de usuario mediante el controlador. Entonces, si usa runOnUIThread, tenga cuidado de no hacer cálculos pesados ​​sobre él. También sincronice el uso de Hanlder para publicar la actualización y el progreso. es mejor que sea fácil de usar. –

1

siguiendo la respuesta de HitOdessit.

Puede crear una clase como esta.

public class Global{ 
    private static Handler mHandler = new Handler(Looper.getMainLooper()); 
    public static void runOnUiThread(Runnable action){ 
     mHandler.post(action); 
    } 
} 

Y luego llámalo así.

Global.runOnUiThread(new Runnable(){ 
    //Your code 
}); 

Y esto se puede ejecutar desde cualquier lugar (donde tenga acceso a su clase Global).

0

¿Cuál sería la mejor manera de actualizar mi UI? ¿Debería ir a Handler o runOnUiThread?

Si su Runnable necesita actualizar su IU, publíquelo en runOnUiThread.

Pero no siempre es posible publicar Runnable en UI Thread.

Piense en el escenario, donde necesita ejecutar Operación de red/IO O invoque un servicio web. En este caso, no puede publicar Runnable en UI Thread. Se lanzará android.os.NetworkOnMainThreadException

Este tipo de Runnable debe ejecutarse en diferentes hilos como HandlerThread. Después de completar su operación, puede enviar el resultado de vuelta al Subproceso UI utilizando Handler, que se ha asociado con Subproceso UI.

public void onClick(View view) { 

    // onClick on some UI control, perform Network or IO operation 

    /* Create HandlerThread to run Network or IO operations */ 
    HandlerThread handlerThread = new HandlerThread("NetworkOperation"); 
    handlerThread.start(); 

    /* Create a Handler for HandlerThread to post Runnable object */ 
    Handler requestHandler = new Handler(handlerThread.getLooper()); 

    /* Create one Handler on UI Thread to process message posted by different thread */ 

    final Handler responseHandler = new Handler(Looper.getMainLooper()) { 
     @Override 
     public void handleMessage(Message msg) { 
      //txtView.setText((String) msg.obj); 
      Toast.makeText(MainActivity.this, 
        "Runnable on HandlerThread is completed and got result:"+(String)msg.obj, 
        Toast.LENGTH_LONG) 
        .show(); 
     } 
    }; 

    NetworkRunnable r1 = new NetworkRunnable("http://www.google.com/",responseHandler); 
    NetworkRunnable r2 = new NetworkRunnable("http://in.rediff.com/",responseHandler); 
    requestHandler.post(r1); 
    requestHandler.post(r2); 

} 

class NetworkRunnable implements Runnable{ 
    String url; 
    Handler uiHandler; 

    public NetworkRunnable(String url,Handler uiHandler){ 
     this.url = url; 
     this.uiHandler=uiHandler; 
    } 
    public void run(){ 
     try { 
      Log.d("Runnable", "Before IO call"); 
      URL page = new URL(url); 
      StringBuffer text = new StringBuffer(); 
      HttpURLConnection conn = (HttpURLConnection) page.openConnection(); 
      conn.connect(); 
      InputStreamReader in = new InputStreamReader((InputStream) conn.getContent()); 
      BufferedReader buff = new BufferedReader(in); 
      String line; 
      while ((line = buff.readLine()) != null) { 
       text.append(line + "\n"); 
      } 
      Log.d("Runnable", "After IO call:"+ text.toString()); 

      Message msg = new Message(); 

      msg.obj = text.toString(); 

      /* Send result back to UI Thread Handler */ 
      uiHandler.sendMessage(msg); 


     } catch (Exception err) { 
      err.printStackTrace(); 
     } 
    } 
} 
Cuestiones relacionadas