Android Handler算是一個(gè)很神奇的東西吧,為什么這么說呢,因?yàn)閯傞_始學(xué)習(xí)Android的時(shí)候講師就一值在說Handler的重要性,下面就來看看對(duì)Handler的淺度理解吧:
一.什么是Handler
?Handler是Android給我們提供用來更新UI的一套機(jī)制,是一套消息處理機(jī)制,可以通過它來發(fā)送消息和處理消息。那作為開發(fā)者的我們,不禁會(huì)疑問?Google為什么要設(shè)計(jì)這套機(jī)制呢?這是為了解決在非UI線程中更新UI組件比較麻煩的問題。那么Android為什么不能在非UI線程中更新呢?首先Android的UI控件不是線程安全的,這是因?yàn)楸苊舛嗑€程并發(fā)所帶來不安全問題。例如作一個(gè)假設(shè),現(xiàn)在在子線程中刷新界面,同時(shí)也在UI線程中刷新界面,就會(huì)出現(xiàn)刷新不同步,簡(jiǎn)單來講通過Handler就可以更新UI操作切換到主線程中執(zhí)行。
二.Handler機(jī)制
?Handler機(jī)制主要角色
Message:消息,就是一個(gè)載體,包含消息ID,消息處理對(duì)象和處理的數(shù)據(jù)等,統(tǒng)一放到MessageQueue,最終由Handler處理。
Handler:用于同一個(gè)進(jìn)程的線程間通信,消息處理者,專門負(fù)責(zé)Message的發(fā)送和處理。我們使用Handler時(shí),一般通過handleMessage(Message msg)來處理Message,也就是統(tǒng)一處理消息的回調(diào),確保自己發(fā)出的消息也是自己來處理。
MessageQueue:由名字可推出這是隊(duì)列,就是存放Handler發(fā)送過來的消息,按照先進(jìn)先出的順序規(guī)則來執(zhí)行。將鏈表的數(shù)據(jù)結(jié)構(gòu)以Message來串聯(lián)起來,等待Looper的抽取,為什么需要隊(duì)列呢?因?yàn)橥痪€程在一個(gè)時(shí)間只能處理一個(gè)消息。因此需要隊(duì)列來保存這些消息,然后挨個(gè)挨個(gè)拿出來處理,創(chuàng)建一個(gè)線程時(shí)并不會(huì)自動(dòng)創(chuàng)建MessageQueue,但是主線程創(chuàng)建時(shí)會(huì)默認(rèn)創(chuàng)建Looper對(duì)象,而Looper創(chuàng)建時(shí)就會(huì)創(chuàng)建MessageQueue,其他非主線程需要looper的時(shí)候就會(huì)通過調(diào)用prepare函數(shù)來實(shí)現(xiàn)。
Looper:首先要理解一個(gè)線程是一段可執(zhí)行的代碼,作為App的主線程,不能讓代碼執(zhí)行完,因?yàn)榇a執(zhí)行完的話app就會(huì)自動(dòng)退出,因此不能讓主線程不能讓代碼段執(zhí)行,只能在代碼中插入一個(gè)死循環(huán),這時(shí)候Looper的作用就體現(xiàn)出來了,將主線程變成Looper線程。并且這時(shí)主線程就會(huì)在等其他線程發(fā)消息(更新UI和Activity狀態(tài)等等)那,另外,Looper不斷從消息隊(duì)列拿出消息給主線程,也就是無限循環(huán)去查找是否有消息,有就去處理,沒有的話就一直等待,一個(gè)MessageQueue需要一個(gè)Looper。
Thread:負(fù)責(zé)調(diào)度整個(gè)消息的循環(huán)。
通過上面可以得知:Handler的作用是發(fā)送和處理消息,Handler發(fā)送的消息必須被送到指定MessageQueue中,也就是說,要讓Handler正常工作就必須有一個(gè)MessageQueue,但是MessageQueue是由Looper來抽取自身的Message,也因此當(dāng)前線程中必須有一個(gè)Looper對(duì)象。
圖解:

Handler深度理解
根據(jù)上面可得:每一個(gè)線程都必須有Looper,但是我們不禁會(huì)有疑問?主線程我們并沒有創(chuàng)建Looper?其實(shí)主線程是ActivityThread,ActivityThread被創(chuàng)建的時(shí)候就會(huì)初始化Looper。

上面紅色箭頭就是主線程創(chuàng)建Looper對(duì)象代碼語句。那么我們繼續(xù)進(jìn)入Looper去看看究竟是什么操作。

果然上面所分析的幾個(gè)主要角色都在:Looper,MessageQueue,Thread,但是還多了一個(gè)ThreadLocal,這個(gè)是什么呢?其實(shí)這個(gè)是一個(gè)線程內(nèi)部的數(shù)據(jù)存儲(chǔ)類,通過它可以在指定線程中存儲(chǔ)數(shù)據(jù),數(shù)據(jù)存儲(chǔ)以后,只有在指定的線程獲取到存儲(chǔ)數(shù)據(jù),對(duì)于其他線程來說則無法獲取到數(shù)據(jù),后面例子再詳細(xì)敘述。

這時(shí)候又有疑問,為什么主線程中有一個(gè)死循環(huán),但是沒有造成阻塞呢?那我們從ActivityThread類開始分析:這個(gè)并不是一個(gè)真正的線程,就只是一個(gè)類,從main方法看到有Looper,那找找其對(duì)應(yīng)的Handler,ActivityThread有一個(gè)內(nèi)部類,繼承Handler,并找到handleMessage

仔細(xì)觀察:Activity的生命周期都有對(duì)應(yīng)的case條件,并且service的生命周期等等都有條件。也就是通過loop來分發(fā)消息內(nèi)部類的Handler,就會(huì)進(jìn)入handleMessage。就會(huì)根據(jù)對(duì)應(yīng)的條件來執(zhí)行對(duì)應(yīng)的代碼,不斷執(zhí)行傳遞過來的消息。那么可以總結(jié)來說:ActivityThread的main方法主要是來做消息循環(huán)的,如果消息循環(huán)退出了,那么程序就退出了。但是從隊(duì)列里取出消息可能會(huì)造成阻塞,如果某個(gè)消息處理的時(shí)間過于長(zhǎng),那么會(huì)影響UI線程的刷新,就造成卡頓現(xiàn)象。不會(huì)造成卡在的真正原因主要有二:
1.當(dāng)沒有消息來的時(shí)候就會(huì)wait,有句柄寫的時(shí)候就會(huì)喚醒,進(jìn)行等待。
2.所有的UI更新操作都通過handler來發(fā)消息。如各種的點(diǎn)擊事件都會(huì)造成句柄寫的操作來喚醒等待。
主線程是UI線程,優(yōu)先級(jí)很高,主線程的死循環(huán)會(huì)不會(huì)特別消耗CPU資源呢?
其實(shí)如果主線程的隊(duì)列里沒有消息時(shí),就會(huì)阻塞在loop的queue.next()里,這時(shí)候主線程就會(huì)釋放CPU資源進(jìn)入休眠狀態(tài),直到下個(gè)消息進(jìn)來時(shí)就會(huì)喚醒主線程,現(xiàn)在是通過pipe管道來寫入數(shù)據(jù),類似I/0,不占用資源。
三.例子實(shí)踐
下面簡(jiǎn)單寫一個(gè)小例子加深理解:
倒計(jì)時(shí)例子:
public
classMainActivityextendsActivity{
privateTextView text_one;
privatemHandler mhandler =newmHandler(this);
@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_main);
? ? ? ? text_one = findViewById(R.id.text_one);
? ? ? ? start();
? ? }
//Handler靜態(tài)內(nèi)部類 防止內(nèi)存泄漏
privatestaticclassmHandlerextendsHandler{
? ? ? WeakReference<MainActivity> weakReference;
publicmHandler(MainActivity mainActivity){
weakReference =newWeakReference(mainActivity);
? ? ? }
@Override
publicvoidhandleMessage(Message msg){
? ? ? ? ? MainActivity mainActivity = weakReference.get();
if(mainActivity !=null){
? ? ? ? ? ? ? ? mainActivity.text_one.setText(String.valueOf(msg.arg1));
? ? ? ? ? }
? ? ? }
? ? }
privatevoidstart(){
newThread(newRunnable() {
@Override
publicvoidrun(){
for(inti =10;i>0;i--){
Message msg =newMessage();
msg.what =01;
? ? ? ? ? ? ? ? ? ? msg.arg1 = i;
? ? ? ? ? ? ? ? ? ? mhandler.sendMessage(msg);
try{
Thread.sleep(1000);
}catch(InterruptedException e) {
? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
//計(jì)時(shí)結(jié)束后先不管
? ? ? ? ? ? }
? ? ? ? }).start();
? }
@Override
protectedvoidonDestroy(){
super.onDestroy();
if(mhandler !=null){
mhandler.removeCallbacksAndMessages(null);
? ? ? }
? }
以上就是對(duì)Handler的理解,謝謝觀看!