1, 為什么使用Handler?
Android的UI要求更新只能在UI線程,因?yàn)榘沧渴菃尉€程模型。如果任意線程都可以更新UI的話,線程安全問(wèn)題處理起來(lái)會(huì)相當(dāng)麻煩復(fù)雜,就會(huì)出現(xiàn)頁(yè)面錯(cuò)亂。所以就規(guī)定了Android的是單線程模型,只允許在UI線程更新UI操作。
也就是在Android中更新Ui必須在主線程,在子線程更新Ui會(huì)報(bào)子線程不能修改UI異常。
你想想安卓的頁(yè)面一會(huì)被這個(gè)線程修改,一會(huì)被別的線程更改。用戶體驗(yàn)就會(huì)很差,給別人一種不可控制的感覺(jué)。
作用:
線程間通訊,更新UI的機(jī)制,消息處理機(jī)制
Handler主要涉及4個(gè)類,分別是Handler、Looper、Message、MessageQueue。
1,消息的分發(fā):Handler 發(fā)送和接收消息
2,消息的實(shí)體 :Message
3,消息隊(duì)列的機(jī)制,怎么保證消息的有序存儲(chǔ)和取出: MessageQueue
4,消息的線程間的通訊:Looper 消息的輪詢機(jī)制,類似電機(jī)一直循環(huán)獲取消息

面試提問(wèn):
1,Handler為什么會(huì)內(nèi)存泄露:
長(zhǎng)生命周期的引用短生命周期的對(duì)象,得不到釋放內(nèi)存;

ActivityThred長(zhǎng)生命周期--->Loop-->MessageQueue-->message-->handler --》Activity 短生命周期對(duì)象
2,Message可以如何創(chuàng)建,哪種效果更好?
用Message.obtain()獲取,緩存池,防止對(duì)象頻繁創(chuàng)建、銷毀造成內(nèi)存抖動(dòng)。
不用重復(fù)去創(chuàng)建 new Meaage ,
3、一個(gè)線程有幾個(gè)Looper?可以有幾個(gè)Handler?
一個(gè)線程只能有一個(gè)Looper,Looper.loop的時(shí)候,會(huì)形成死循環(huán),此時(shí)即使有多個(gè)Looper也沒(méi)有意義。那是怎么保證Looper的關(guān)系呢?通過(guò)ThreadLocal保證Looper和Thread的關(guān)系。
而一個(gè)線程可以有很多個(gè)Handler,只要在初始化的時(shí)候得到線程的Looper即可。
// sThreadLocal.get() will return null unless you've called prepare().
@UnsupportedAppUsage
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
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));
}
/**
* 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();
}
4、Looper.loop為什么不會(huì)導(dǎo)致主線程卡死
Looper 死循環(huán),沒(méi)消息會(huì)進(jìn)行休眠不會(huì)卡死,調(diào)用 linux 底層的 epoll 機(jī)制實(shí)現(xiàn)
當(dāng)App啟動(dòng)時(shí),Zygote進(jìn)程會(huì)fork新的進(jìn)程,然后通過(guò)ActivityThread的main方法進(jìn)入應(yīng)用程序。在main方法中,會(huì)啟動(dòng)Looper.loop,而在loop之前,會(huì)通過(guò)thread.attach綁定ActivityManagerService。當(dāng)系統(tǒng)有事件響應(yīng)時(shí),便會(huì)通知ActivityThread的mH進(jìn)行處理。
public static void main(String[] args) {
········
Looper.prepareMainLooper();
········
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
········
Looper.loop();
}
// 用于處理AMS響應(yīng)的事件
class H extends Handler {
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
········
}
源碼分析 :
一 、創(chuàng)建Handler
handler.Callback的消息處理可以“覆蓋”處理器自己的消息處理所以可以設(shè)置一個(gè)默認(rèn)的消息處理注意:。返回值為true才“覆蓋”默認(rèn)的消息處理,如果都沒(méi)有覆蓋就是調(diào)用的handleMessage(MSG) ;方法啦這個(gè)方法就是你在處理程序重寫的方法,消息方法一樣。
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(HomeActivity.this, "msg", Toast.LENGTH_SHORT).show();
}
};
二 、創(chuàng)建 Message發(fā)送消息
Message message = Message.obtain();
message.obj = "自定義handler";
handler.sendMessage(message);
public final class Message implements Parcelable {
public int what;
public Object obj;
Handler target; //通過(guò)target 拿到Handler,從而調(diào)用handleMessage()方法
}
三、MessageQueue 添加消息到消息隊(duì)列
創(chuàng)建 new Looper的時(shí)候就已經(jīng)創(chuàng)建了MessageQueue
MessageQueue是在Looper類里拿的
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
handler.sendMessage 所有的消息都會(huì)走這個(gè)方法,添加到消息隊(duì)列
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.");
}
synchronized (this) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
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;
}
四, Looper類
Looper類怎么來(lái)的呢?
看一下ActivityThread類 頁(yè)面創(chuàng)建的就初始化了
public static void main(String[] args) {
//省略代碼1
Looper.prepareMainLooper();
//省略代碼2
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
//省略代碼3
Looper.loop();
}
繼續(xù)看Looper.prepareMainLooper();方法
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
里面有個(gè) prepare(false);看這個(gè):
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));
}
它new Looper跟進(jìn)去
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
創(chuàng)建主線程時(shí),會(huì)自動(dòng)調(diào)用ActivityThread的1個(gè)靜態(tài)的main();而main()內(nèi)則會(huì)調(diào)用Looper.prepareMainLooper()為主線程生成1個(gè)Looper對(duì)象,同時(shí)也會(huì)生成其對(duì)應(yīng)的MessageQueue對(duì)象。
看ActivityThread的main方法中省略代碼3下面:
Looper.loop();
Looper調(diào)用了靜態(tài)loop方法
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
首先判斷了looper是否存在,不存在就會(huì)拋異常說(shuō)沒(méi)有l(wèi)ooper,讓你調(diào)用prepare方法創(chuàng)建Looper
public static void loop() {
//省略
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
這個(gè)死循環(huán)會(huì)取出Message有就取。沒(méi)有就結(jié)束
msg.target.dispatchMessage(msg);
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
這個(gè)方法,把Message發(fā)個(gè)Handler了。
說(shuō)明:
Looper持有 -->MessageQueue持有-->Message--Message.tager持有--handler持有-->activity 這樣的關(guān)系鏈
所有Looper 死循環(huán)才有取出到Message
本來(lái)想寫一篇詳細(xì)的源碼分析,由于能力和時(shí)間不夠各位我盡力了