1.什么是Handler
Handler是android中消息機(jī)制,Handler運(yùn)行需要通過MessageQueue和Looper來支撐,Handler主要作用就是將一個(gè)任務(wù)切換到指定的線程中
2 Handler使用
發(fā)送三個(gè)消息,通過這三個(gè)來分析MessageQueue
public class HandlerActivity extends AppCompatActivity {
private TextView tv;
private Handler mHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
tv.setText(msg.obj + "");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
tv = findViewById(R.id.tv);
//開啟一個(gè)線程發(fā)送消息
new Thread(new Runnable() {
@Override
public void run() {
Message msg1 = Message.obtain();
msg1.obj = "姚明1";
mHandler.sendMessage(msg1);
Message msg2 = Message.obtain();
msg2.obj = "姚明2";
mHandler.sendMessageDelayed(msg2,1000);
Message msg3 = Message.obtain();
msg3.obj = "姚明3";
mHandler.sendMessageDelayed(msg3,500);
}
}).start();
}
}
3.MessageQueue消息隊(duì)列
線程中更新 UI 的時(shí)候經(jīng)常是調(diào)用 sendMessage() 和 sendMessageDelayed() ,看一下sendMessage() 方法
//默認(rèn)延時(shí)時(shí)間為0
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
...
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
//注意這里,msg.target綁定了我們的this也就是Handler
msg.target = this;
....
return queue.enqueueMessage(msg, uptimeMillis);
}
3.1MessageQueue的核心代碼
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
....
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;
}
通過上邊的這些代碼,我們暫時(shí)還沒有看到 Handler 調(diào)用 handleMessage() 方法,但是有了一個(gè)重要的結(jié)論,我們每次發(fā)送一個(gè)消息都會(huì)被保存到了 MessageQueue 消息隊(duì)列中,消息隊(duì)列中采用的是單鏈表的方式。通過用下面這段代碼發(fā)送消息,在 MessageQueue 中如圖所示。
3.2.MessageQueue內(nèi)如圖所示
Message msg1 = Message.obtain();
msg1.obj = "姚明1";
mHandler.sendMessage(msg1);
Message msg2 = Message.obtain();
msg2.obj = "姚明2";
mHandler.sendMessageDelayed(msg2,1000);
Message msg3 = Message.obtain();
msg3.obj = "姚明3";
mHandler.sendMessageDelayed(msg3,500);
3.3 總結(jié)
???每次發(fā)送一個(gè)消息都會(huì)添加到消息隊(duì)列中,按照when時(shí)間進(jìn)行排序,消息隊(duì)列采用的是單鏈表形式。
4.Loop消息循環(huán)
4.1 子線程中使用Handler
先看一種現(xiàn)象,有時(shí)候我們像下面這么寫會(huì)報(bào)錯(cuò):
new Thread(new Runnable() {
@Override
public void run() {
//子線程中使用Handler
Handler handler = new Handler();
}
}).start();

必須要這樣寫
new Thread(new Runnable() {
Override
public void run() {
//1.創(chuàng)建Looper對(duì)象,獲取當(dāng)前線程,通過當(dāng)前線程獲取ThreadLocalMap對(duì)象,保證一個(gè)線程只有一個(gè)Looper對(duì)象
Looper.prepare();
//2.獲取當(dāng)前的Looper對(duì)象,獲取當(dāng)前的MessagerQueue對(duì)象
Handler handler = new Handler();
//3.發(fā)送消息,將消息添加到消息隊(duì)列中,通過msg.when來進(jìn)行排序
Message msg = Message.obtain();
msg.obj = "姚明"
handler.sendMessage(msg);
//4.獲取當(dāng)前的Looper對(duì)象,獲取當(dāng)前的MessagerQueue對(duì)象,通過死循環(huán)不斷獲取MessageQueue中消息,回掉給Handler的handlerMessage。
Looper.loop();
}
}).start();
我們?cè)谥骶€程中從來沒有調(diào)用過Looper.prepare();這行代碼,為什么就不會(huì)報(bào)錯(cuò)呢。因?yàn)樵谖覀兂绦蛉肟贏ctivityThread中的入口函數(shù) main() 已經(jīng)幫我們調(diào)用了這行代碼
public static void main(String[] args) {
//....省略部分代碼
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
4.2 Looper.prepare()分析
我們來通過看源碼來了解Looper.prepare()到底干了什么。
//靜態(tài)的
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<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));
}
/**
* 1.獲取當(dāng)前線程,通過當(dāng)前線程獲取線程的ThreadLocalMap對(duì)象,一個(gè)線程只有一個(gè)ThreadLocal對(duì)象
* 2.如果map不為空,就添加,key就是我們的sThreadLocal是靜態(tài)的,value就是我們的Looper對(duì)象。
* 3.如果map為空就會(huì)創(chuàng)建ThreadLocalMap
*/
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
//創(chuàng)建ThreadLocalMap
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
//創(chuàng)建MessageQueue,獲取當(dāng)前線程。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
4.2.1 總結(jié)
???Looper.prepare() 就是創(chuàng)建了Looper對(duì)象,通過當(dāng)前線程獲取ThreadLocalMap,通過set來保證一個(gè)線程中只有一個(gè)Looper對(duì)象
4.3 Looper.loop()解析
public static void loop() {
//1.獲取當(dāng)前線程的Looper對(duì)象
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//2.獲取消息隊(duì)列
final MessageQueue queue = me.mQueue;
//3.死循環(huán)不斷獲取消息隊(duì)列中的消息
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
try {
//msg.target就是我們的Handler,在MessageQueue中已經(jīng)提到了msg.target綁定了我們的Handler,可以回去看一下
//3.通過 Handler 執(zhí)行我們Message,這里邊就調(diào)用我們的handleMessage方法
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//回收我們的消息
msg.recycleUnchecked();
}
}
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
//4.回掉我們的handleMessage
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}