編輯:關於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); } }
10-27 15:13:21.382: V/Test(9618): Toast called from Handler.sendMessage()
從這個簡單的例子,我們可以歸納一下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()
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
除了 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); }
那麼其為什麼要放到MessageQueue?放到MessageQueue中有如何跑回到Handler的handleMessage中的呢?
接下來的文章,我們再繼續來學習。
這一篇我們就簡單地介紹了如何使用Handler,簡單的例子,簡單地入門。
結束。
微信作為手機端通訊應用,很多人把它當做常用的通訊工具了,如果你還停留在QQ,還沒有開始使用微信的話,說明你就out了,微信功能強大,微信支付,微信叫滴滴,微
在我們的實際項目中,數據應該說是很多的,我們的ListView不可能一下子把數據全部加載進來,我們可以當滾動條滾動到ListView的底部的時候,給一個更多的提示,當我們
本文實例講述了Android實現仿淘寶購物車增加和減少商品數量功能。分享給大家供大家參考,具體如下:在前面一篇《Android實現的仿淘寶購物車demo示例》中,小編簡單
Android客戶端請求服務器端的詳細解釋1. Android客戶端與服務器端通信方式:Android與服務器通信通常采用HTTP通信方式和Socket通信方式,而HTT