Android中HandlerThread類的解析

來源:互聯網
上載者:User

Android應用中的訊息迴圈由Looper和Handler配合完成,Looper類用於封裝訊息迴圈,類中有個MessageQueue訊息佇列;Handler類封裝了訊息投遞和訊息處理等功能。

系統預設情況下只有主線程(即UI線程)綁定Looper對象,因此在主線程中可以直接建立Handler的執行個體,但是在子線程中就不能直接new出Handler的執行個體了,因為子線程預設並沒有Looper對象,此時會拋出RuntimeException異常:

瀏覽下Handler的預設建構函式就一目瞭然了:

    public Handler() {        if (FIND_POTENTIAL_LEAKS) {            final Class<? extends Handler> klass = getClass();            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&                    (klass.getModifiers() & Modifier.STATIC) == 0) {                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +                    klass.getCanonicalName());            }        }        mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;        mCallback = null;    }

如果需要在子線程中使用Handler類,首先需要建立Looper類執行個體,這時可以通過Looper.prepare()和Looper.loop()函數來實現的。閱讀Framework層源碼發現,Android為我們提供了一個HandlerThread類,該類繼承Thread類,並使用上面兩個函數建立Looper對象,而且使用wait/notifyAll解決了多線程中子線程1擷取子線程2的Looper對象為空白的問題。HandlerThread類完整代碼如下:

/** * Handy class for starting a new thread that has a looper. The looper can then * be used to create handler classes. Note that start() must still be called. */public class HandlerThread extends Thread {private int mPriority; // 線程優先順序private int mTid = -1; // 線程IDprivate Looper mLooper; // 我們需要的Looper對象public HandlerThread(String name) {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;}/** * 在Looper.loop()之前執行動作的回呼函數 */protected void onLooperPrepared() {}public void run() {mTid = Process.myTid();Looper.prepare(); // 建立本線程的Looper對象synchronized (this) {mLooper = Looper.myLooper();notifyAll(); //通知所有等待該線程Looper對象的其他子線程,本線程的Looper對象已就緒}Process.setThreadPriority(mPriority);onLooperPrepared(); //回呼函數Looper.loop(); //開始訊息佇列迴圈mTid = -1;}/** * 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()) {return null;}// If the thread has been started, wait until the looper has been// created.synchronized (this) {while (isAlive() && mLooper == null) {try {wait(); //Looper對象未建立好,等待} catch (InterruptedException e) {}}}return mLooper;}/** * Ask the currently running looper to quit. 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. */public boolean quit() {Looper looper = getLooper();if (looper != null) {looper.quit();return true;}return false;}/** * Returns the identifier of this thread. See Process.myTid(). */public int getThreadId() {return mTid;}}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.