Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android源碼分析之HandlerThread

Android源碼分析之HandlerThread

編輯:關於Android編程

 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。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved