上一篇文章提到了Android系統的UI線程是一種帶消息循環(Looper)機制的線程(http://www.linuxidc.com/Linux/2014-12/110161.htm),同時Android也提供了封裝有消息循環(Looper)的HandlerThread類,這種線程,可以綁定Handler()對象,並通過Handler的sendMessage()函數向線程發送消息,通過handleMessage()函數,處理線程接收到的消息。這麼說比較抽象,那麼,本文就利用基礎的Java類庫,實現一個帶消息循環(Looper)的線程,以幫助初學者理解這樣一個Looper到底是怎麼工作的。
1. 首先,我們完成一個簡單的線程框架。
public class LooperThread {
private volatile boolean mIsLooperQuit = false;
private Thread mThread;
public void start() {
if( mThread != null ) {
return;
}
mIsLooperQuit = false;
mThread = new Thread(mLooperRunnable);
mThread.start();
}
public void stop() {
if( mThread == null ) {
return;
}
mIsLooperQuit = true;
mThread = null;
}
protected Runnable mLooperRunnable = new Runnable() {
@Override
public void run() {
while( !mIsLooperQuit ) {
}
}
};
}
如上述代碼所示,mLooperRunnable.run()循環執行線程任務,mIsLooperQuit則是線程退出循環的條件。下面,我們將添加消息的發送和處理代碼。
2. 添加線程循環的消息發送和處理代碼
(1) 定義消息結構體,創建消息隊列
public class LooperThread {
private Queue<Message> mMessageQueue = new LinkedList<Message>();
public static class Message {
int what;
}
}
(2) 創建互斥鎖和條件變量
public class LooperThread {
private Lock mLock = new ReentrantLock();
private Condition mCondition = mLock.newCondition();
}
(3) 創建發送消息的函數
//發送消息,由外部其他模塊調用,發送消息給線程
public void sendMessage( Message message ) {
if( mThread == null ) {
return;
}
mLock.lock();
mMessageQueue.add(message); //添加消息到消息隊列
mCondition.signal(); //通知線程循環,有消息來了,請立即處理
mLock.unlock();
}
(4) 創建處理消息的函數
//處理消息,由線程內部調用
public void handleMessage(Message message) {
//這裡可以通過一個Callback來回調監聽者
}
(5) 在mLooperRunnable.run()循環中解析消息
protected Runnable mLooperRunnable = new Runnable() {
@Override
public void run() {
while( !mIsLooperQuit ) {
mLock.lock();
Message message = null;
try {
while( !mIsLooperQuit && mMessageQueue.isEmpty() ) {
mCondition.await(); //沒有消息到來則休眠
}
message = mMessageQueue.poll();
}
catch (InterruptedException e) {
e.printStackTrace();
}
finally {
mLock.unlock();
}
handleMessage(message );
}
};
}
(6) 修改線程的Stop()函數,喚醒休眠的消息循環
public void stop() {
if( mThread == null ) {
return;
}
mIsLooperQuit = true;
mLock.lock();
mCondition.signal();
mLock.unlock();
mMessageQueue.clear();
mThread = null;
}
到這裡,一個基本的帶有消息循環的線程類封裝就完成了,相信大家應該從編寫這段代碼的過程中,理解了系統是如何實現消息循環的。完整的代碼見博文最後的附件,有任何疑問歡迎留言或者來信[email protected]交流。
相關附件下載地址:
------------------------------------------分割線------------------------------------------
免費下載地址在 http://linux.linuxidc.com/
用戶名與密碼都是www.linuxidc.com
具體下載目錄在 /2014年資料/12月/4日/Android開發實踐:自定義帶消息循環(Looper)的工作線程
下載方法見 http://www.linuxidc.com/Linux/2013-07/87684.htm
------------------------------------------分割線------------------------------------------
最簡單的Ubuntu Touch & Android 雙系統安裝方式 http://www.linuxidc.com/Linux/2014-01/94881.htm
在Nexus上實現Ubuntu和Android 4.4.2 雙啟動 http://www.linuxidc.com/Linux/2014-05/101849.htm
Ubuntu 14.04 配置 Android SDK 開發環境 http://www.linuxidc.com/Linux/2014-05/101039.htm
64位Ubuntu 11.10下Android開發環境的搭建(JDK+Eclipse+ADT+Android SDK詳細) http://www.linuxidc.com/Linux/2013-06/85303.htm
Ubuntu 14.04 x64配置Android 4.4 kitkat編譯環境的方法 http://www.linuxidc.com/Linux/2014-04/101148.htm
Ubuntu 12.10 x64 安裝 Android SDK http://www.linuxidc.com/Linux/2013-03/82005.htm
更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11