Handler是什么?
handler是線程間消息傳遞的橋梁,主要用來發(fā)送消息和處理消息。
為什么需要做線程間的通信?
Android不能在主線程(UI線程 / ActivityThread)中做耗時操作,而子線程不能更新UI,當子線程需要更新UI時候就需要通過Handler切換到主線程中。
為什么子線程不能更新UI?
Android的UI控件是線程不安全的,如果在多線程中訪問同一個控件,會讓控件處于一個不可知的狀態(tài)。
為何系統(tǒng)不對控件進行加鎖呢?
加鎖機制會讓控件邏輯變得復雜,同時降低了控件的訪問效率,加鎖會阻止某些線程的執(zhí)行。
Handler如何發(fā)送消息和處理消息?

-
Handler
負責Message的發(fā)送和處理,按照先進先出執(zhí)行,內部使用的是單鏈表結構。
sendMessage( )發(fā)送消息去消息池,handleMessage( )進行消息的處理。 -
MessageQueue
負責管理和存儲由Handler發(fā)送過來的Message。讀取會自動刪除消息,單鏈表維護,插入和刪除上有優(yōu)勢。 -
Message
需要被傳遞的消息,分為硬件產生的消息和軟件產生的消息。 -
Looper
Looper通過loop( )開啟無限循環(huán),通過MessageQueue的next( )方法不斷獲取消息,一旦拿到消息就會分發(fā)給Handler進行處理,否則會在next( )中阻塞。當Looper( )的quit( ) 調用會導致MessageQueue中的quit( )調用,next( )返回null,loop退出。
主線程創(chuàng)建的時候會創(chuàng)建一個Looper,同時也會在Looper內部創(chuàng)建一個消息隊列。而在創(chuàng)建Handler的時候取出當前線程的Looper,并通過該Looper對象獲取消息隊列,然后Handler在子線程通過Message.enqueueMessage在消息隊列添加消息。Looper.loop( )開啟循環(huán)從隊列中獲取消息后通過dispatchMessage( )發(fā)送給Handler,最終由handleMessage( )進行處理。
一個線程可以有多個Handler?
一個線程只會有一個Looper和一個消息隊列,但是可以有多個Handler( )。
Looper的死循環(huán)為什么不會導致系統(tǒng)卡死?
主線程的主要方法是消息循環(huán),是要維持主線程一直存活的,一旦消息循環(huán)退出也就意味這應用退出。Looper.loop( )可能會引起線程的阻塞,但只要他的消息循環(huán)沒有被阻塞可以一直處理消息就不會產生ANR。造成ANR的原因不是主線程阻塞,而是處理消息的消息循環(huán)阻塞,無法響應用戶的操作,不能即時的更新UI。阻塞與程序無響應沒有必然聯(lián)系,雖然在沒有消息的時候消息循環(huán)會阻塞在MessageQueue的next( )中(此時主線程會釋放CPU資源進入休眠狀態(tài)),但是只要有新消息的產生可以立刻進行處理是不會發(fā)生程序無響應的。
可以在子線程中創(chuàng)建Handler嗎?
可以創(chuàng)建,但是需要自己維護一個Looper,并且要在所有事情做完后調用quit( )來終止消息循環(huán),否則這個線程會一直處于等待(阻塞)狀態(tài)。主線程在創(chuàng)建的時候會自動創(chuàng)建Looper,會自動管理處理發(fā)送過來的消息。Loooer在那個線程創(chuàng)建,就綁定那個線程,并且Handler是在他關聯(lián)的Looper對應的線程中處理消息的。
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
Looper.loop();
}
});
Handler導致內存泄漏?
1.handler允許我們發(fā)送延時消息postDelay( ) ,如果在延時期間用戶關閉了Activity,那么該Activity就會泄漏。因為Message會持有Handler,又因為Java的特性,內部類會持有外部類,這樣Activity就被Handler所持有,導致泄漏。
1-1.所以,將Handler定義為靜態(tài)內部類,在內部持有外部Activity的弱引用,并且在Activity退出的時候移除所有消息。
2.手動為一個子線程創(chuàng)建Looper,當消息處理完畢后,不手動退出的情況下會一直處于等待狀態(tài),而以quit( )退出Looper后,線程會立刻關閉。
Handler、Thread和HandlerThread的差別?
handler實現(xiàn)了線程間的通信,thread是java進程中執(zhí)行運算的最小單位,也是執(zhí)行處理機調度的基本單位。Android沒有對Java的Thread進行封裝,而是提供了一個繼承自Thread的HandlerThread,內部維護了一個Looper,這是Handler消息機制必不可少的,有了looper才能做到消息的發(fā)放和處理,如果不用HandlerThread就需要自行維護一個Looper。
Message創(chuàng)建方式?
Message m = new Message();
Message m2 = Message.obtain();
Message m3 = mHandler.obtainMessage();
第一種方法是直接實例化一個Message對象,后兩者直接從Android的消息池(單項鏈表,默認消息池數量為10)中獲取一個Message實例,這樣可以避免多生成Message實例浪費內存。
消息池中Message的對象是通過recycle()放進去的.在Looper的loop()方法的最后調用了Message對象的recycle()方法來回收這個Message對象,通過recycle()將這個Message對象的數據清空然后鏈接到消息池中(采用的頭插法)。
其他子線程更新UI的方法?
除了Handler還有
- runOnUiThread( )
new Thread(new Runnable() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mDiv.setVisibility(View.GONE);
}
});
}
}).start();
- view.Post( )
mNickName.post(new Runnable() {
@Override
public void run() {
mNickName.setText("********");
}
});
- AsyncTask