Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中利用Handler實現消息的分發機制(零)

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

編輯:關於Android編程

在之前一篇介紹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,簡單的例子,簡單地入門。

結束。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved