Android中利用Handler實現訊息的分發機制(零)

來源:互聯網
上載者:User

標籤:handler   android   非同步訊息處理機制   message   messagequeue   

在之前一篇介紹AsyncTask的文章中,我們在最後講到,AsyncTask是利用Handler的訊息非同步處理機制,將操作結果,利用Message傳回主線程,從而進行UI線程的更新的。

而在我們日常的開發工作中,Handler也是我們經常使用的類之一,那麼Handler的主要作用是什嗎?

Handler 的主要作用就是對訊息(訊息可以是我們想做的一些UI更新,也可以是其他的一些不可見的操作,如操作資料庫等)的非同步處理機制,而相信大家都瞭解非同步概念。

簡單地說一下:

1)從程式的角度來看,就是當執行某行代碼的時候,發送了一個非同步請求(訊息),程式不需要在此行代碼上繼續等待下去,而是能夠繼續執行之後的代碼。

2)從使用者的角度來看,使用者發送了一個訊息,不需要什麼事也不做,就在那傻等,而可以去做其他的事情,當對應的訊息被處理完之後 ,就會通過回調機制處理對應的結果。

所以,Android中Handler的訊息非同步處理機制,能夠給使用者提供一個更加合理及友好的使用者體驗。當然,Android是用Handler來實現,其他的平台環境,也有著自己的一套非同步實現機制,原理一樣,名稱不同而已。

既然我們是做Android開發的,那麼我們肯定就要好好地學習一下Handler的使用,探究一下隱藏在Handler之後的代碼架構。

首先,我們還是從簡單的例子來入門,學習一下,如何使用Handler。

代碼如下:

public class MainActivity extends ActionBarActivity {    private static final int MSG_ID_1 = 1;    private static final int MSG_ID_2 = 2;    private Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            switch (msg.what) {            case MSG_ID_1:                Log.v("Test", "Toast called from Handler.sendMessage()");                break;            case MSG_ID_2:                break;            }                    }    };        protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Message message = mHandler.obtainMessage();        message.what = MSG_ID_1;        mHandler.sendMessage(message);    }}

當我們啟動程式的時候,我們可以看到,在LogCat裡面就會看到,已經列印出了如下的資訊:

10-27 15:13:21.382: V/Test(9618): Toast called from Handler.sendMessage()

而這正是我們在handler的handleMessage中對msg.what = MSG_ID_1 的情況下進行處理的。

從這個簡單的例子,我們可以歸納一下Handler的使用步驟,大概有以下幾步:

1)建立一個Handler對象,並且實現其 handleMessage(Message msg) 方法,如代碼中:

private Handler mHandler = new Handler() {

而實現handleMessage方法一步,我們可以看到,會擷取一個Message對象。

Message對象封裝了一些參數,常用的大概有以下幾個:

a)what 參數:這是一個 int 值,經常是我們用來區分訊息的一個ID,比如例子中,我們將MSG_ID_1在建立訊息的時候賦值給msg.what。

b)obj 參數:這是一個Object對象。通過obj參數,可以把任何對象賦給訊息,然後在handleMessage中進行處理,而這也是Handler在非同步處理中傳遞資料的方法。

c)arg1, arg2 等參數:上述a),b) 兩個參數是我們最常用的Message的參數了,基本上也需要這兩個參數就足夠了,不過Message還是提供了其他的一些欄位供我們使用,如argX等,也就是 arguments的縮寫。

2)當建立好Handler對象之後,第二步就需要建立一個Message對象了,建立Message對象有兩種方法:

2.1)直接建立新對象,代碼如下:

Message msg = new Message()

2.2)利用Handler.obtainMessage()方法,也即上面代碼中使用的方式,如下:

Message message = mHandler.obtainMessage();

一般情況下,我們建議使用第二種方式,為什麼呢?

因為在Message的內部中維護了一個類似訊息池的對象,當我們使用Handler來對Message進行分發的時候,處理完之後,Message對象並不一定會被馬上銷毀,而是有可能放到一個訊息池中。

當利用Handler的obtainMessage方法,Handler會去從訊息池中擷取一個已經存在的對象,並初始化好其資訊,這樣,我們就不需要再重新去建立一個對象,浪費一些記憶體,在嵌入式應用,記憶體不是很大的情況下,這是對效能的一種最佳化。

在建立Message的時候,我們就可以對msg.what進行賦值,目的就是為了Handler在handleMessage的時候,可以判斷這個訊息的用途或目的是什麼。

當然,不同的需求,肯定有不同的處理,這就具體情況具體分析了。

3)當訊息(Message)建立好了之後,我們就可以利用Handler的sendMessage來進行發送訊息了,之後,這個訊息就會被其handler所捕獲,從而進行處理了。


接下來,我們就再擴充一下這個例子,代碼如下:

public class MainActivity extends ActionBarActivity {    private static final int MSG_ID_1 = 1;    private static final int MSG_ID_2 = 2;    private Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            switch (msg.what) {            case MSG_ID_1:                Log.v("Test", "Toast called from Handler.sendMessage()");                break;            case MSG_ID_2:                String str = (String) msg.obj;                Log.v("Test", str);                break;            }                    }    };        protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Message message = mHandler.obtainMessage();        message.what = MSG_ID_1;        mHandler.sendMessage(message);                Message msg2 = mHandler.obtainMessage();        msg2.obj = "I'm String from Message 2";        msg2.what = MSG_ID_2;        mHandler.sendMessage(msg2);    }}

而其對應的結果如下:

10-27 15:35:19.168: V/Test(12135): Toast called from Handler.sendMessage()10-27 15:35:19.168: V/Test(12135): I'm String from Message 2

由此,我們可以看到,利用obj參數,我們將String對象給傳到handleMessage中去了。


除了 sendMessage方法,發送訊息時, Handler還可使用如下的方法:

    public final boolean sendMessage(Message msg)    {        return sendMessageDelayed(msg, 0);    }    public final boolean sendEmptyMessage(int what)    {        return sendEmptyMessageDelayed(what, 0);    }    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {        Message msg = Message.obtain();        msg.what = what;        return sendMessageDelayed(msg, delayMillis);    }      public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {        Message msg = Message.obtain();        msg.what = what;        return sendMessageAtTime(msg, uptimeMillis);    }    public final boolean sendMessageDelayed(Message msg, long delayMillis)    {        if (delayMillis < 0) {            delayMillis = 0;        }        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);    }    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {        MessageQueue queue = mQueue;        if (queue == null) {            RuntimeException e = new RuntimeException(                    this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);            return false;        }        return enqueueMessage(queue, msg, uptimeMillis);    }        public final boolean sendMessageAtFrontOfQueue(Message msg) {        MessageQueue queue = mQueue;        if (queue == null) {            RuntimeException e = new RuntimeException(                this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);            return false;        }        return enqueueMessage(queue, msg, 0);    }

我們可以看到,無論是sendEmptyMessage還是sendMessage,其實最終都是通過調用sendMessageAtTime方法,將對應的Message對象放入一個MessageQueue中的。

那麼其為什麼要放到MessageQueue?放到MessageQueue中有如何跑回到Handler的handleMessage中的呢?

接下來的文章,我們再繼續來學習。

這一篇我們就簡單地介紹了如何使用Handler,簡單的例子,簡單地入門。

結束。

Android中利用Handler實現訊息的分發機制(零)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.