2012-09-27 103 views
37

我碰到過HandlersrunOnUiThread的概念。但對我而言,它似乎仍然是一個疑問,因爲它們確切地區分了哪些事實。爲什麼使用處理程序而runOnUiThread也一樣?

它們都是用來從後臺線程執行UI操作的。但在我們選擇這兩種方法時要考慮哪些因素。

例如,考慮在後臺執行Web服務的RunnableThread,現在我想更新UI。

什麼是最好的方式來更新我的用戶界面?我應該去HandlerrunOnUiThread

我仍然知道我可以使用AsyncTask並利用onPostExecute。但我只想知道其中的差異。

+2

'runOnUiThread'只是將'Runnable'發佈到'Handler'的快捷方式。 'Handler'是Android定義的每個(?)交叉線程通信工具的基礎(例如'AsyncTask'的'onPostExecute'使用'Handler'來傳遞'doInBackground'的結果)。 – zapl

回答

63

Activity.runOnUiThread()是更通用的Handlers的特例。通過Handler,您可以在自己的線程中創建自己的事件查詢。使用Handlersdefault constructor實例化不是意思是「代碼將在UI線程上運行」。默認情況下,處理程序綁定到Thread,從中實例化它們。

要創建Handler這是保證綁定到UI(主)線程應該創建綁定到主尺蠖這樣Handler對象:

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

而且,如果你檢查runOnuiThread()方法的實現,它使用Handler做的事情:

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

正如你可以從上面的代碼片段看,Runnable action將是EXE如果從UI線程調用runOnUiThread(),立即立即取消。否則,它會將其發佈到Handler,稍後將在稍後執行。

+0

但不包含「從中實例化的線程」。通常是UI線程? –

+8

@Mike,這完全取決於你的代碼。通常情況下,處理程序是從主線程實例化的,但是有很多情況下開發人員在創建'Handler'實例時沒有關於當前線程的確切信息。因此,如果開發人員需要保證處理程序將在主線程中執行,則應該使用'new Handler(Looper.getMainLooper())'。 – HitOdessit

+0

明白這一點非常有幫助。 –

0

處理程序是舊的方式(API級別1)做的東西,然後AsycTask(API級別3)被引入,同時更強調使用runOnUIThread(API級別1)。您應儘可能避免使用處理程序,並根據您的需要選擇其他兩個。

+1

但是爲什麼?我完全需要差異。你能解釋更多嗎? –

+0

沒有區別,你可以用Handlers和Loopers實現同樣的事情,但是這些技巧可以幫助你避免錯誤。請參閱http://en.wikipedia.org/wiki/Syntactic_sugar – Animesh

1

處理程序有很多工作就像消息傳遞和頻繁的UI更新,如果你啓動一個線程任何運行的任務。一個處理程序允許您發送和處理信息,並與一個線程的MessageQueue ,,相關Runnable對象,這是非常在許多應用,如藍牙聊天,,無線上網聊天......和處理有用已爲法PostDelay和PostAtTime,通過它可以圍繞任何觀點發揮到動畫和變化知名度等

你必須看看在這個

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

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

+0

是的,但爲什麼不在這裏使用runOnUIThread? –

+1

runOnUIThread總是在UI線程上執行計算,而使用處理程序U可以啓動線程以在那裏執行大量計算並將結果發佈到UI線程使用處理程序。所以如果你使用runOnUIThread,那麼請小心不要對它進行繁重的計算。異步同樣使用Hanlder裏面來發布更新和進度。它更好地取決於你的易用性。 –

1

關注HitOdessit的回答。

您可以像這樣創建一個類。

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

然後像這樣調用它。

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

這可以從任何地方(您可以訪問您的全球課程)運行。

0

什麼是最好的方式來更新我的用戶界面?我應該去處理程序還是runOnUiThread?

如果您的Runnable需要更新UI,請在runOnUiThread上發佈。

但是並不總是可以在UI線程上發佈Runnable

想想您需要執行的場景網絡/ IO操作或調用Web服務。在這種情況下,您不能將Runnable發佈到UI線程。它會拋出android.os.NetworkOnMainThreadException

這些類型的Runnable應運行在不同的線程上,如HandlerThread。完成操作後,您可以使用已與UI線程關聯的Handler將結果發回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(); 
     } 
    } 
} 
相關問題