基本信息
1.Handler-控制器
2.Looper-輪詢
3.Message-消息對象
4.MessageQueue-單鏈表結構的消息隊列
一個消息的前生今世
一般情形下,涉及到異步的操作才需要引入handler來接收異步操作的結果,來更新UI信息.所以常規操作是這樣
圖片引用自
https://zhuanlan.zhihu.com/p/25222485
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
textView.setText("對UI進行操作");
}
};
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.mytv);
new Thread(new Runnable() {
@Override
public void run() {
//模擬耗時操作
SystemClock.sleep(3000);
handler.sendMessage(new Message());
}
}).start();
}
首先創建一個handler
第二創建一個Thread
Thread處理完某項操作以後,通過handler.sendMessage(msg)把異步的結果發送到消息隊列MessageQueue中,
然後我們通過複寫handlerMessage()完成該次操作.
問題
Looper呢?MessageQueue呢?
這TM到底怎麼關聯起來的.
圖同樣取自https://zhuanlan.zhihu.com/p/25222485
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 判斷是否爲空,不爲空
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
重頭戲
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
Message類中幾個有趣的東西
Handler target;
Message next;
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
重點標註target,你會發現尼瑪:Message在創建的時候就關聯了handler.
關於Looper
public static void prepare() {
prepare(true);
}
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));
}
重點注意ThreadLocal,
這是個什麼類呢?
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
ThreadLocal用於保存某個線程變量:對於同一個static ThreadLocal,不同線程只能從中get,set,remove自己的變量,而不會影響其他線程的變量。
1、ThreadLocal.get: 獲取ThreadLocal中當前線程變量的值。
2、ThreadLocal.set: 設置ThreadLocal中當前線程變量的值。
3、ThreadLocal.remove: 移除ThreadLocal中當前線程變量的值。
4、ThreadLocal.initialValue: ThreadLocal沒有被當前線程賦值時或當前線程剛調用remove方法後調用get方法,返回此方法值。
這個太重要了.這是個啥子勒.
ThreadLocal保存保存了各自線程的Looper,Looper又包含MessageQueue,Looper的構造器
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
sendMsg發送一次,ThreadLocal就set一次.
Looper中loop方法是個死循環(在主線程的死循環爲啥沒引起ANR呢?)
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
//......
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//......
msg.recycleUnchecked();
}
呀哈,誰污染,誰治理,誰發送,誰處理
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
結束:handler收到了消息,最後過上了沒羞沒糙的生活