Android Hanlder機制分析(二) HandThread Handler.Obtain()
阿新 • • 發佈:2019-01-22
(一)建立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 傳送訊息的時候,最好使用第二種方法,這樣可以減少不必要的記憶體開銷。