Android Handler訊息傳遞機制,androidhandler

來源:互聯網
上載者:User

Android Handler訊息傳遞機制,androidhandler

1. Handler訊息傳遞機制初步認識:什麼是Handler?
handler通俗一點講就是用來在各個線程之間發送資料的處理對象。在任何線程中,只要獲得了另一個線程的handler,則可以通過 handler.sendMessage(message)方法向那個線程發送資料。基於這個機制,我們在處理多線程的時候可以建立一個thread,這個thread擁有UI線程中的一個handler。當thread處理完一些耗時的操作後通過傳遞過來的handler向UI線程發送資料,由UI線程去更新介面。
主線程:運行所有UI組件,它通過一個訊息佇列來完成此任務。裝置會將使用者的每項操作轉換為訊息,並將它們放入正在啟動並執行訊息佇列中。主線程位於一個迴圈中,並處理每條訊息。如果任何一個訊息用時超過5秒,Android將拋出ANR。所以一個任務用時超過5秒,應該在一個獨立線程中完成它,或者延遲處理它,當主線程空閑下來再返回來處理它。

2.常用類:(Handler、Looper、Message、MessageQueue)
Message:訊息,其中包含了訊息ID,訊息處理對象以及處理的資料等,由MessageQueue統一列隊,終由Handler處理。
Handler:處理者,負責Message的發送及處理。使用Handler時,需要實現handleMessage(Message msg)方法來對特定的Message進行處理,例如更新UI等。Handler類的主要作用:(有兩個主要作用)1)、在背景工作執行緒中發送訊息;2)、在主線程中獲w/取、並處理訊息。
MessageQueue:訊息佇列,用來存放Handler發送過來的訊息,並按照FIFO規則執行。當然,存放Message並非實際意義的儲存,而是將Message串聯起來的,等待Looper的抽取。
Looper:訊息泵,不斷地從MessageQueue中抽取Message執行。因此,一個MessageQueue需要一個Looper。

3.Handler、Looper、Message、MessageQueue之間的關係:

  • Looper和MessageQueue一一對應,建立一個Looper的同時,會建立一個MessageQueue;
  • 而Handler與它們的關係,只是簡單的聚集關係,即Handler裡會引用當前線程裡的特定Looper和MessageQueue;
  • 在一個線程中,只能有一個Looper和MessageQueue,但是可以有多個Handler,而且這些Handler可以共用一個Looper和MessageQueue;
  • Message被存放在 MessageQueue中,一個 MessageQueue中可以包含多個Message對象

【備忘:】
Looper對象用來為一個線程開啟一個訊息迴圈,從而操作MessageQueue;
預設情況下,Android建立的線程沒有開啟訊息迴圈Looper,但是主線程例外。
系統自動為主線程建立Looper對象,開啟訊息迴圈;
所以主線程中使用new來建立Handler對象。而子線程中不能直接new來建立Handler對象就會異常。
子線程中建立Handler對象,步驟如下:
Looper.prepare();
Handler handler = new Handler() {
//handlemessage(){}
}
Looper.loop();

4.Handler類中常用方法:
(1) handleMessage() 用在主線程中,構造Handler對象時,重寫handleMessage()方法。該方法根據背景工作執行緒返回的訊息標識,來分別執行不同的操作。
(2) sendEmptyMessage() 用在背景工作執行緒中,發送空訊息。
(3) sendMessage() 用在背景工作執行緒中,立即發送訊息。

5.Message訊息類中常用屬性:
(1) arg1 用來存放整型資料
(2) arg2 用來存放整型資料
(3) obj 用來存放Object資料
(4) what 用於指定使用者自訂的訊息代碼,這樣便於主線程接收後,根據訊息代碼不同而執行不同的相應操作。

上一下Demo的範例程式碼:

private Handler handler = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        text_main_info = (TextView) findViewById(R.id.text_main_info);        pDialog = new ProgressDialog(MainActivity.this);        pDialog.setMessage("Loading...");        image_main = (ImageView) findViewById(R.id.image_main);        // 主線程中的handler對象會處理背景工作執行緒中發送的Message。根據Message的不同編號進行相應的操作。        handler = new Handler() {                public void handleMessage(android.os.Message msg) {                        // 背景工作執行緒中要發送的資訊全都被放到了Message對象中,也就是上面的參數msg中。要進行操作就要先取出msg中傳遞的資料。                        switch (msg.what) {                        case 0:                                // 背景工作執行緒發送what為0的資訊代表線程開啟了。主線程中相應的顯示一個進度對話方塊                                pDialog.show();                                break;                        case 1:                                // 背景工作執行緒發送what為1的資訊代表要線程已經將需要的資料載入完畢。本案例中就需要將該資料擷取到,顯示到指定ImageView控制項中即可。                                image_main.setImageBitmap((Bitmap) msg.obj);                                break;                        case 2:                                // 背景工作執行緒發送what為2的資訊代表背景工作執行緒結束。本案例中,主線程只需要將進度對話方塊取消即可。                                pDialog.dismiss();                                break;                        }                }        };        new Thread(new Runnable() {                @Override                public void run() {                        // 當背景工作執行緒剛開始啟動時,希望顯示進度對話方塊,此時讓handler發送一個空資訊即可。                        // 當發送這個資訊後,主線程會回調handler對象中的handleMessage()方法。handleMessage()方法中                        // 會根據message的what種類來執行不同的操作。                        handler.sendEmptyMessage(0);                        // 背景工作執行緒執行訪問網路,載入網狀圖片的任務。                        byte[] data = HttpClientHelper.loadByteFromURL(urlString);                        // 背景工作執行緒將網路訪問擷取的位元組數組產生Bitmap位元影像。                        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,                                        data.length);                        // 背景工作執行緒將要發送給主線程的資訊都放到一個Message資訊對象中。                        // 而Message對象的構建建議使用obtain()方法產生,而不建議用new來產生。                        Message msgMessage = Message.obtain();                        // 將需要傳遞到主線程的資料放到Message對象的obj屬性中,以便於傳遞到主線程。                        msgMessage.obj = bitmap;                        // Message對象的what屬性是為了區別資訊種類,而方便主線程中根據這些類別做相應的操作。                        msgMessage.what = 1;                        // handler對象攜帶著Message中的資料返回到主線程                        handler.sendMessage(msgMessage);                        // handler再發出一個空資訊,目的是告訴主線程背景工作執行緒的任務執行完畢。一般主線程會接收到這個訊息後,                        // 將進度對話方塊關閉                        handler.sendEmptyMessage(2);                }        }).start();}

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.