2012-09-27 9 views
37

Mi sono imbattuto in entrambi i concetti e runOnUiThread. Ma per me sembra ancora essere un dubbio su quali fatti differiscono esattamente.Perché utilizzare gli handler mentre runOnUiThread fa lo stesso?

Entrambi sono progettati per eseguire azioni dell'interfaccia utente da un thread in background. Ma quali sono i fattori da considerare mentre scegliamo tra i due metodi.

Ad esempio, considerare un RunnableThread che esegue un servizio Web in background e ora voglio aggiornare l'interfaccia utente.

Quale sarebbe il modo migliore per aggiornare la mia UI? Devo andare per Handler o runOnUiThread?

So ancora che potrei usare uno AsyncTask e fare uso di onPostExecute. Ma voglio solo sapere la differenza.

+2

'runOnUiThread' è solo una scorciatoia per pubblicare un' Runnable' su un 'Handler'. 'Handler' è la base di ogni (?) Funzione di comunicazione incrociata definita da Android (ad es.' AsyncTask''s 'onPostExecute' usa un' Handler' per fornire il risultato da 'doInBackground'). – zapl

risposta

63

Activity.runOnUiThread() è un caso speciale di più generico Handlers. Con Handler puoi creare la tua query di evento all'interno della tua discussione. L'utilizzo di Handlers è stato creato con default constructornon corrisponde a significa che "il codice verrà eseguito sul thread dell'interfaccia utente" in generale. Per impostazione predefinita, i gestori sono stati associati a Thread da cui è stato creato l'istanza.

Per creare Handler che è garantito per legarsi a UI (principale) filo si dovrebbe creare Handler oggetto binded al principale Looper come questo:

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

Inoltre, se si seleziona la realizzazione di runOnuiThread() metodo, sta usando Handler di fare le cose:

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

Come si può vedere dal frammento di codice di cui sopra, Runnable action sarà exe tagliato immediatamente, se runOnUiThread() viene chiamato dal thread dell'interfaccia utente. Altrimenti, lo invierà allo Handler, che verrà eseguito in un momento successivo.

+0

Ma non "Thread da cui è stato istanziato." di solito il thread dell'interfaccia utente? –

+8

@ Mike, questo dipende totalmente dal tuo codice. Spesso sì, i gestori sono istanziati dal thread principale, ma ci sono molti casi in cui lo sviluppatore non ha informazioni esatte sul thread corrente durante la creazione dell'istanza di 'Handler'. Pertanto, lo sviluppatore dovrebbe usare 'new Handler (Looper.getMainLooper())' se ha bisogno di garanzie che il gestore eseguirà nel thread principale. – HitOdessit

+0

capito grazie che è molto utile. –

0

I gestori erano alla vecchia maniera (Livello API 1) di fare roba, quindi sono stati introdotti AsycTask (Livello API 3), insieme a una maggiore attenzione all'utilizzo di runOnUIThread (Livello API 1). Dovresti evitare di usare gli handler il più possibile e preferire gli altri due a seconda delle tue necessità.

+1

Ma perché? Ho bisogno esattamente della differenza. Puoi per favore spiegare di più. –

+0

Non c'è differenza, è possibile ottenere le stesse cose con Gestori e Loopers, ma queste tecniche aiutano a evitare errori. Vedi http://en.wikipedia.org/wiki/Syntactic_sugar – Animesh

1

Handler ha molti lavorano come passaggio di messaggi e l'aggiornamento dell'interfaccia utente frequente se si avvia un thread per ogni esecuzione di un compito .A Handler permette di inviare e processo di messaggi e oggetti Runnable associati MessageQueue di un thread ,, che è molto utile in molte applicazioni, come bluetooth videochat ,, wifi chat ... e conduttore ha come metodo PostDelay e PostAtTime con cui è possibile giocare qualsiasi vista per animare e cambiare la visibilità e così via

si deve guardare in questo

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

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

+0

Sì, ma perché non usare runOnUIThread qui? –

+1

runOnUIThread esegue sempre il calcolo sul thread dell'interfaccia utente, mentre l'utilizzo di Handler U può attivare un thread per eseguire calcoli pesanti e pubblicare il risultato sul thread dell'interfaccia utente utilizzando Handler. Quindi, se usi runOnUIThread, fai attenzione a non fare calcoli pesanti su di esso. Async usa anche Hanlder per postare aggiornamenti e progressi. meglio dipende dalla tua facilità d'uso. –

1

Segue la risposta di HitOdessit.

È possibile creare una classe come questa.

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

E quindi chiamarlo così.

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

E questo può essere eseguito da qualsiasi luogo (dove è possibile accedere alla classe Globale).

0

Quale sarebbe il modo migliore per aggiornare la mia UI? Dovrei andare per Handler o runOnUiThread?

Se il tuo Runnable deve aggiornare l'interfaccia utente, pubblicarlo su runOnUiThread.

Ma non è sempre possibile postare Runnable sul thread UI.

Pensare allo scenario, in cui si desidera eseguire il funzionamento di rete/IO Oppure richiamare un servizio Web. In questo caso, non puoi postare Runnable in UI Thread. Lanciare android.os.NetworkOnMainThreadException

Questi tipi di Runnable devono essere eseguiti su thread diversi come HandlerThread. Dopo aver completato l'operazione, è possibile postare i risultati sul thread dell'interfaccia utente utilizzando Handler, che è stato associato a Thread 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(); 
     } 
    } 
}