標籤:android style blog class code java
HandlerThread是一種特殊的Thread,也就是有Looper的thread,既然有looper的話,那我們就可以用此looper來
建立一個Handler,從而實現和它的互動,比如你可以通過與它關聯的Handler對象在UI線程中發訊息給它處理。HandlerThread
一般可以用來執行某些background的操作,比如讀寫檔案(在此HandlerThread而非UI線程中)。既然還是一個Thread,那麼
和一般的Thread一樣,也要通過調用其start()方法來啟動它。它只是Android替我們封裝的一個Helper類,其源碼相當簡潔,我們
下面來看看,很簡單。
和以往一樣,我們先來看看欄位和ctor:
int mPriority; // 線程優先順序 int mTid = -1; // 線程id Looper mLooper; // 與線程關聯的Looper public HandlerThread(String name) { // 提供個名字,方便debug super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; // 沒提供,則使用預設優先順序 } /** * Constructs a HandlerThread. * @param name * @param priority The priority to run the thread at. The value supplied must be from * {@link android.os.Process} and not from java.lang.Thread. */ public HandlerThread(String name, int priority) { super(name); mPriority = priority; // 使用使用者提供的優先順序,基於linux優先順序,取值在[-20,19]之間 }
代碼很簡單,相關的分析都直接寫在代碼的注釋裡了,值得注意的是這裡的priority是基於linux的優先順序的,而不是Java Thread
類裡的MIN_PRIORITY,NORM_PRIORITY,MAX_PRIORITY之類,請注意區分(其實認真閱讀方法的doc即可)。
接下來看看此類的關鍵3個方法:
/** * Call back method that can be explicitly overridden if needed to execute some * setup before Looper loops. */ protected void onLooperPrepared() { // callback方法,如果你願意可以Override放自己的邏輯;其在loop開始前執行 } @Override public void run() { mTid = Process.myTid(); Looper.prepare(); // 此方法我們前面介紹過,會建立與線程關聯的Looper對象 synchronized (this) { // 進入同步塊,當mLooper變的可用的使用,調用notifyAll通知其他可能block在當前對象上的線程 mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); // 設定線程優先順序 onLooperPrepared(); // 調用回呼函數 Looper.loop(); // 開始loop mTid = -1; // reset為invalid值 } /** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason is isAlive() returns false, this method will return null. If this thread * has been started, this method will block until the looper has been initialized. * @return The looper. */ public Looper getLooper() { if (!isAlive()) { // 如果線程不是在alive狀態則直接返回null,有可能是你忘記調start方法了。。。 return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { // 進入同步塊,當條件不滿足時無限等待, try { // 直到mLooper被設定成有效值了才退出while(當然也可能是線程狀態不滿足); wait(); // run方法裡的notifyAll就是用來喚醒這裡的 } catch (InterruptedException e) { // 忽略InterruptedException } } } return mLooper; // 最後返回mLooper,此時可以保證是有效值了。 }
當你new一個HandlerThread的對象時記得調用其start()方法,然後你可以接著調用其getLooper()方法來new一個Handler對象,
最後你就可以利用此Handler對象來往HandlerThread發送訊息來讓它為你幹活了。
最後來看2個退出HandlerThread的方法,其實對應的是Looper的2個退出方法:
/** * Quits the handler thread‘s looper. * <p> * Causes the handler thread‘s looper to terminate without processing any * more messages in the message queue. * </p><p> * Any attempt to post messages to the queue after the looper is asked to quit will fail. * For example, the {@link Handler#sendMessage(Message)} method will return false. * </p><p class="note"> * Using this method may be unsafe because some messages may not be delivered * before the looper terminates. Consider using {@link #quitSafely} instead to ensure * that all pending work is completed in an orderly manner. * </p> * * @return True if the looper looper has been asked to quit or false if the * thread had not yet started running. * * @see #quitSafely */ public boolean quit() { Looper looper = getLooper(); // 注意這裡是調用getLooper而不是直接使用mLooper, if (looper != null) { // 因為mLooper可能還沒初始化完成,而調用方法可以 looper.quit(); // 等待初始化完成。 return true; } return false; } /** * Quits the handler thread‘s looper safely. * <p> * Causes the handler thread‘s looper to terminate as soon as all remaining messages * in the message queue that are already due to be delivered have been handled. * Pending delayed messages with due times in the future will not be delivered. * </p><p> * Any attempt to post messages to the queue after the looper is asked to quit will fail. * For example, the {@link Handler#sendMessage(Message)} method will return false. * </p><p> * If the thread has not been started or has finished (that is if * {@link #getLooper} returns null), then false is returned. * Otherwise the looper is asked to quit and true is returned. * </p> * * @return True if the looper looper has been asked to quit or false if the * thread had not yet started running. */ public boolean quitSafely() { Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false; }
通過代碼我們可以看到其內部都是delegate給了Looper對象,而Looper我們在前面也介紹過了,感興趣的同學可以翻看前面的分析或者
查看這2個方法的doc,寫的都很詳細。
至此這個簡單的Handy class就算分析完畢了。在實際的開發中,如果你只是要做某些背景操作(短暫的,比如把某些設定檔案load
到記憶體中),而不需要更新UI的話,那你可以優先使用HandlerThread而不是AsyncTask。
接下來準備分析下Android提供的資料存放區機制SharedPreferences,敬請期待。。。