Android源碼分析之HandlerThread

來源:互聯網
上載者:User

標籤: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,敬請期待。。。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.