2012-09-27 10 views
37

Ich bin sowohl auf Handlers und runOnUiThread Konzepte gestoßen. Aber für mich scheint es immer noch zweifelhaft zu sein, auf welchen Fakten sie sich genau unterscheiden.Warum Handler verwenden, während runOnUiThread das gleiche tut?

Sie beide sollen UI-Aktionen von einem Hintergrundthread ausführen. Aber was sind die Faktoren, die berücksichtigt werden müssen, während wir zwischen den beiden Methoden wählen?

Zum Beispiel betrachtet ein RunnableThread, die einen Web-Service im Hintergrund ausführt, und jetzt will ich die Benutzeroberfläche aktualisieren.

Was wäre der beste Weg, um meine Benutzeroberfläche zu aktualisieren? Sollte ich für Handler oder runOnUiThread gehen?

Ich weiß immer noch, ich könnte eine AsyncTask verwenden und onPostExecute verwenden. Aber ich will nur den Unterschied wissen.

+2

'runOnUiThread' ist nur eine Abkürzung für das Veröffentlichen eines' Runnable' zu ​​einem 'Handler'. "Handler" ist die Basis jeder (?) Cross-Thread-Kommunikationseinrichtung, die von Android definiert wird (z. B. "AsyncTask" verwendet "onPostExecute" einen "Handler", um das Ergebnis von "doInBackground" zu liefern). – zapl

Antwort

63

Activity.runOnUiThread() ist ein Sonderfall von generischen Handlers. Mit Handler können Sie Ihre eigene Ereignisabfrage in Ihrem eigenen Thread erstellen. Mit Handlers instanziiert mit default constructornicht bedeutet "Code wird auf UI-Thread" im Allgemeinen ausgeführt. Standardmäßig sind Handler an Thread gebunden, von denen sie instanziiert wurden.

Handler erstellen, das Gewinde (Haupt-) an UI binden, wird garantiert, dass Sie Handler Objekt binded zu Haupt Looper wie dies schaffen sollen:

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

Außerdem, wenn Sie die Implementierung von runOnuiThread() Methode überprüfen, es ist Handler mit den Dingen zu tun:

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

Wie Sie oben von Code-Schnipsel sehen kann, wird Runnable action exe ​​sein Cute sofort, wenn runOnUiThread() aus dem UI-Thread aufgerufen wird. Andernfalls wird es an die Handler, die zu einem späteren Zeitpunkt ausgeführt wird.

+0

Aber nicht "Thread, von dem sie instanziiert wurde." normalerweise der UI-Thread? –

+8

@Mike, das hängt völlig von Ihrem Code ab. Oft werden Handler aus dem Hauptthread instanziiert, aber es gibt viele Fälle, in denen der Entwickler beim Erstellen der Handler-Instanz keine genauen Informationen über den aktuellen Thread hat. Daher sollte der Entwickler 'new Handler (Looper.getMainLooper()) 'verwenden, wenn er Garantien benötigt, die der Handler im Hauptthread ausführen wird. – HitOdessit

+0

habe es dank, das ist sehr hilfreich. –

0

Handlers waren die alte Art und Weise (API Stufe 1) von Sachen zu tun, und dann AsycTask (API Stufe 3) eingeführt wurden, zusammen mit einer stärkeren Konzentration auf runOnUIThread (API Stufe 1) verwendet wird. Sie sollten es vermeiden, so viele Handler wie möglich zu verwenden, und die anderen beiden bevorzugen Sie je nach Ihrem Bedarf.

+1

Aber warum? Ich brauche den Unterschied genau. Kannst du bitte mehr erklären. –

+0

Es gibt keinen Unterschied, Sie können die gleichen Dinge mit Handlern und Loopern erreichen, aber diese Techniken helfen Ihnen, Fehler zu vermeiden. Siehe http://en.wikipedia.org/wiki/Syntactic_sugar – Animesh

1

Handler hat viele Arbeiten wie Nachricht und häufigen UI Update vorbei, wenn Sie einen Thread für jeden Lauf einer Aufgabe .A Handler ermöglicht es Ihnen, beginnen zu senden und zu verarbeiten Nachricht und Runnable mit einem Message Thread zugeordnet Objekte ,, was sehr nützlich in vielen Anwendungen wie bluetooth Chat ,, Wi-Fi-Chat ... und Handler hat sich als Methode PostDelay und PostAtTime, mit denen Sie um jede Ansicht spielen zu animieren und ändern die Sichtbarkeit und so weiter

Sie in dieser

aussehen muss

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

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

+0

Ja, aber warum nicht runOnUIThread hier verwenden? –

+1

runOnUIThread führt immer eine Berechnung im UI-Thread durch, während Using Handler U einen Thread auslösen kann, um dort umfangreiche Berechnungen auszuführen und das Ergebnis mit Handler im UI-Thread zu veröffentlichen. Also, wenn Sie runOnUIThread verwenden, dann seien Sie vorsichtig, machen Sie keine schwere Berechnung. Async zu verwenden Hanlder innen, um Update und Fortschritt zu posten. es hängt besser von Ihrem einfach zu verwenden ab. –

1

HitOdessit Antwort folgen.

Sie können eine Klasse wie diese erstellen.

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

Und dann rufen Sie es so.

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

Und dies kann von überall ausgeführt werden (wo Sie Zugriff auf Ihre globale Klasse haben).

0

Was wäre der beste Weg, um meine Benutzeroberfläche zu aktualisieren? Soll ich Handler oder runOnUiThread verwenden?

Wenn Ihre Runnable die Benutzeroberfläche aktualisieren muss, geben Sie sie unter runOnUiThread ein.

Aber es ist nicht immer möglich, Runnable auf UI-Thread zu buchen.

Denken Sie an Szenario, wo Sie möchten Netzwerk/IO-Operation ausführen Oder rufen Sie einen Web-Service. In diesem Fall können Sie Runnable nicht an UI-Thread senden. Es wird android.os.NetworkOnMainThreadException

Diese Art von Runnable sollte auf anderen Thread wie HandlerThread laufen. Nach Abschluss der Operation können Sie das Ergebnis mithilfe von Handler, das mit dem UI-Thread verknüpft wurde, zurück an den UI-Thread senden.

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(); 
     } 
    } 
} 
Verwandte Themen