Handler筆記
什么是handler機制?
handler機制的主要成員
1、handler:負責發送處理消息
2、message:消息的信息的載體
3、messageQueue:存放message的隊列
4、looper:handler機制的動力,無限循環的從messageQueue隊列中取出message給handler
1、Handler
(1)我們先來看看handler的構造方法
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
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 = callback;
mAsynchronous = async;
}
(2)默認的構造方法走了 Handler(Callback callback, boolean async) 構造方法,此方法用 mLooper = Looper.myLooper();獲取了looper,然后又用looper創建了messageQueue
2、Looper
在Looper類中
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
注意上面的注釋 返回一個與當前線程關聯的Looper對象
那Looper是怎么創建的呢,既然有get方法,那應該就有set方法。搜索sThreadLocal.set,果然找到了
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
說明prepare方法直接創建了一個當前線程的Looper
在UI主線程中,會默認的創建好Looper對象,而在子線程中要使用本線程的Handler需要手動創建Looper對象,如下
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
}
};
Looper.loop();
}
}
3、MessageQueue
在handler中我們知道MessageQueue對象通過
mQueue = mLooper.mQueue;
其中的消息是怎么來的呢我們我們通過handler的sendMessage()方法來進行分析
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
handler的sendMessage()方法又調用了
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
sendMessageAtTime()又調用了
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
此方法先獲取了全局的messageQueue對象mQueue最后通過MessageQueue.enqueueMessage()將message存到了messageQueue隊列中
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
通過上面的分析我們知道了messageQueue是怎么進數據的,后邊我們分析一下怎么從里面取數據
我們在子線程中使用Handler的示例中最后一步 調用Looper.loop();然后我們來看看
public static void loop() {
final Looper me = myLooper();
······
for (;;) {
Message msg = queue.next(); // might block
······
try {
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
······
}
}
在Looper.loop();方法中我們可以看到for循環中從queue中取出message,然后message是怎么給到handler呢?
在msg.target.dispatchMessage(msg);這一步中我們先看看target是個什么?轉到message類中會發現
/*package*/ Handler target;
target是個handler實例 由此可以得出整個message的傳播回路
總結:
在一個線程中創建handler、looper、messageQueue
handler把帶有信息的message通過sendmessage()發送給messageQueue隊列,然后looper通過Looper.loop()無限循環從messageQueue中取出message,然后在發送給handler,handler在handleMessage()方法中處理信息
最后感謝前人的好文章的指導,個人根據個人的理解總結如有不對的地方,請留言。
https://blog.csdn.net/reakingf/article/details/52054598
https://blog.csdn.net/pgg_cold/article/details/79400435?utm_source=blogxgwz2
https://blog.csdn.net/qian520ao/article/details/78262289?locationNum=2&fps=1
https://blog.csdn.net/qq_32770809/article/details/79132363?utm_source=blogxgwz1