2012-06-26 71 views
43

要更新從其他線程的GUI,基本上有兩種主要的方法:更新GUI:VS的Runnable消息

  1. 使用了java.lang.Runnable與任何這些方法:

    Activity.runOnUiThread(Runnable) 
    View.post(Runnable) 
    View.postDelayed(Runnable, long) 
    Handler.post(Runnable) 
    
  2. 使用android.os.Message:

    Handler.sendMessage(Message)/Handler.handleMessage(Message) 
    

您也可以使用AsyncTask,但我的問題更多集中在更新非常簡單的組件的用例上。讓我們來看看它是如何將使用來完成這兩種方法:

  1. 使用的Runnable:

    TextViev tv = ...; 
    final String data = "hello"; 
    Runnable r = new Runnable() { 
    
        @Override 
        public void run(){ 
         tv.setText(data); 
        } 
    
    }; 
    //Now call Activity.runOnUiThread(r) or handler.post(r), ... 
    
  2. 使用的消息:

    Message m = handler.obtainMessage(UPDATE_TEXT_VIEW, "hello"); 
    handler.sendMessage(m); 
    
    //Now on handler implementation: 
        @Override 
        public void handleMessage(Message msg) { 
         if(msg.what == UPDATE_TEXT_VIEW){ 
          String s = (String) msg.obj; 
          tv.setText(data); 
         } ... //other IFs? 
        } 
    

恕我直言,消息是沒有辦法的辦法,以因爲:

  • 不容易理解新的非android程序員(處理程序掛鉤到其線程在建設過程中)。
  • 如果消息跨越進程邊界,則對象有效內容應該是可包裝的。
  • 消息被重複使用(容易出錯,如果不妥善清理?)
  • 該處理器具有雙重作用(其發送的消息,同時也處理它們)
  • 信息屬性是公開的,而且還提供了getter/setter。

另一方面,Runnables遵循衆所周知的命令模式,並且程序員更友好,更易讀。

那麼使用消息超過Runnables有什麼優勢?在現代Android編程中,消息是否被推入了背景?使用Runnables無法完成的消息有什麼可以做的嗎?

在此先感謝。

回答

4

Handler接口提供了更多的功能比runOnUiThread(),根據文檔:

有一處理程序的兩個主要用途是:
(1)來調度消息和可運行爲在某一時刻被執行未來
(2)排隊在與您自己不同的線程上執行的動作。

runOnUiThread只做(2)的一個子集。即「排隊要在UI線程執行的操作」,除非你需要這些額外的功能runOnUiThread是足夠的和優選的方式

所以IMO。

+0

好吧,也許這個想法沒有清楚地暴露在我的問題。它不是Handler vs Runnables,而是Handler.sendMessage與Runnable的替代品。 (該組還包括'Handler.postDelayed'和'Handler.postAtTime',其中包含#1) –

+0

您實際上已在您的帖子中解釋了差異。我不知道我可以添加到這些的任何其他差異。 – Caner

12

Messages可以重複使用,因此它會創建更少的對象和更少的GC。您最終還會得到更少的類和匿名類型。

一個很大的優點是發送MessageHandler的類不需要知道任何關於該Message的實現的任何信息。這可以幫助封裝取決於它的使用位置。

最後考慮

mHandler.obtainMessage(DO_STUFF, foo).sendToTarget(); 

VS

final Foo tempFoo = foo; 
mHandler.post(new Runnable(){ 
    @Override 
    public void run(){ 
     doStuff(tempFoo); 
    } 
}; 

如果你有幾個地方之間,你將不得不在doStuff()清潔的區別,前者是更可讀,你就會有更少代碼重複。

+3

Runnables也可以被重用,它也是一個接口,你可以用比你所顯示的更清晰的方式實例化一個接口(這也是我發佈的:))。 –

+1

FWIW我認爲這裏的關鍵是消息不需要建立/發送它們來了解消息處理的方式。這是向客戶公開您希望他們向您發送特定信息的一種方式,但不會採取什麼措施。如果您希望能夠在運行時交換不同的處理程序,而不會混淆生成消息的代碼,那也很方便。 因此,在發佈問題的情況下,這樣的簡單UI更新與消息或可運行性相當。但是肯定有消息確實會提供額外好處的情況。 –

+0

主要原因imo爲什麼Messages會有用是因爲android操作系統實際上將它們排隊,這就是爲什麼在任何時候您都可以確保稍後發送的消息只會在先前發送的消息被執行後纔會執行。 – Bhargav

17

我會說使用MessageRunnable之間幾乎沒有什麼區別。它主要歸結爲個人偏好。爲什麼?查看源代碼,您會發現發佈Runnable使用相同的確切消息傳遞機制。它只需將Runnable附加到Message併發送。

4.4.2源代碼

public final boolean post(Runnable r) { 
    return sendMessageDelayed(getPostMessage(r), 0); 
} 

private static Message getPostMessage(Runnable r) { 
    Message m = Message.obtain(); 
    m.callback = r; 
    return m; 
} 

編號:Grep Code - Handler

+0

你好,你能確認我們什麼時候需要實現handleMessage方法嗎?我的意思是當我們需要Handler的孩子類時?因爲我們可以通過調用handler.post()來直接與主UI線程通信。方法。 – UnKnown

+0

建議您張貼作爲新問題 –

+0

在這裏,我創建了一個新問題。 https://stackoverflow.com/questions/47336380/when-we-need-to-override-handlers-handlemessage-method – UnKnown

1

我喜歡RunnableMessage。我認爲使用Runnable的代碼比Message清晰得多,因爲事件處理代碼非常接近事件。另外,您可以避免定義常量和開關情況的開銷。我不認爲使用Runnable違反封裝。您可以將Runnable.run()中的代碼提取到外部類中的另一個方法中,例如on...Event(),或者將其包裝到EventHandler對象中。這兩種方法都比使用Message更清晰,尤其是當您需要在Message中存儲參考時,因爲使用Runnable可以避免向下轉換msg.obj。而無名字段msg.obj也容易出錯,有時無法理解。

而且Runnable也可以通過將其作爲字段存儲來重複使用。