標籤:
http://ticktick.blog.51cto.com/823160/1565272
上一篇文章提到了Android系統的UI線程是一種帶訊息迴圈(Looper)機制的線程,同時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]交流。
【轉】Android開發實踐:自訂帶訊息迴圈(Looper)的背景工作執行緒