1. 程式人生 > >Android Hanlder機制分析(二) HandThread Handler.Obtain()

Android Hanlder機制分析(二) HandThread Handler.Obtain()

(一)建立looper執行緒的方法比較

在上一篇中,講到了在UI執行緒中Handler的原理及使用。如果我們需要在自己的子執行緒中建立Handler就需要自己為子執行緒繫結looper了。如下:

   private MyHandlerTread mHandlerThread;
   mHandlerThread = new MyHandlerTread();
   mHandlerThread.start();
   class MyHandlerTread extends Thread {
       public Handler myHandler;
       public void
run() { Looper.prepare(); myHandler = new Handler() { public void handleMessage(Message msg){ } }; Looper.loop(); } }

當然,我們也可以使用簡單的方法對上面的方法進行實現,那就是使用HandlerThread。

       private HandlerThread myHandlerThread;
       myHandlerThread= new
HandlerThread("myhandler-thread"); Handler myHandler; myHandlerThread= new HandlerThread("myhandler-thread"); myHandlerThread.start(); myHandler = new Handler(myHandlerThread.getLooper()) { public void handleMessage(Message msg){ ...... } };

通過HandlerThread,我們可以更加簡單的將子執行緒變為looper執行緒。下面來看看HandlerThread是是怎麼實現的。

public class HandlerThread extends Thread {
             ......
                 @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
}

    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }

從上面的原始碼可以看到,在第6行和13行 同樣是執行了looper.prepare()和Loop.looper();在呼叫new Handler(myHandlerThread.getLooper()) 的時候,實則是呼叫到了

public Handler(Looper looper) {
        this(looper, null, false);
    }

    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

此處就和之前的方法一樣了。

(二)Handler 傳送訊息的兩種方法比較

使用Handler的時候必然會往MessageQueue傳送訊息。通常的寫法如下
(1)

Message msg = new Message();
msg.what = xxx;
msg.ar1 = XXX;
mHandler.sendMessage(msg);

(1)

myHandler.sendMessage(myHandler.obtainMessage(what,arg1,arg2));

這兩種方式傳送訊息由和區別呢?
方法一種可以看到,我們先new 了一個message,然後通過mHandler傳送出去。在第二種方法中 myHandler.obtainMessage(what,arg1,arg2)的返回值也是一個message。咋然一看沒有什麼區別,那我們繼續往下看。

public final Message obtainMessage(int what, int arg1, int arg2)
    {
        return Message.obtain(this, what, arg1, arg2);
    }

Message的obtain有多個過載方法,但是最關鍵的是
 /**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

這個方法中,會去從訊息池中取出一個訊息 進行清空後 返回。如果訊息池為空才會去新建一個新的訊息物件。因此,在每次通過handler 傳送訊息的時候,最好使用第二種方法,這樣可以減少不必要的記憶體開銷。