Android应用程序消息处理机制(Looper、Handler)分析(1)
??? ? ? ?Android應(yīng)用程序是通過消息來(lái)驅(qū)動(dòng)的,系統(tǒng)為每一個(gè)應(yīng)用程序維護(hù)一個(gè)消息隊(duì)例,應(yīng)用程序的主線程不斷地從這個(gè)消息隊(duì)例中獲取消息(Looper),然后對(duì)這些消息進(jìn)行處理(Handler),這樣就實(shí)現(xiàn)了通過消息來(lái)驅(qū)動(dòng)應(yīng)用程序的執(zhí)行,本文將詳細(xì)分析Android應(yīng)用程序的消息處理機(jī)制。
?? ? ? ?前面我們學(xué)習(xí)Android應(yīng)用程序中的Activity啟動(dòng)(Android應(yīng)用程序啟動(dòng)過程源代碼分析和Android應(yīng)用程序內(nèi)部啟動(dòng)Activity過程(startActivity)的源代碼分析)、Service啟動(dòng)(Android系統(tǒng)在新進(jìn)程中啟動(dòng)自定義服務(wù)過程(startService)的原理分析和Android應(yīng)用程序綁定服務(wù)(bindService)的過程源代碼分析)以及廣播發(fā)送(Android應(yīng)用程序發(fā)送廣播(sendBroadcast)的過程分析)時(shí),它們都有一個(gè)共同的特點(diǎn),當(dāng)ActivityManagerService需要與應(yīng)用程序進(jìn)行并互時(shí),如加載Activity和Service、處理廣播待,會(huì)通過Binder進(jìn)程間通信機(jī)制來(lái)知會(huì)應(yīng)用程序,應(yīng)用程序接收到這個(gè)請(qǐng)求時(shí),它不是馬上就處理這個(gè)請(qǐng)求,而是將這個(gè)請(qǐng)求封裝成一個(gè)消息,然后把這個(gè)消息放在應(yīng)用程序的消息隊(duì)列中去,然后再通過消息循環(huán)來(lái)處理這個(gè)消息。這樣做的好處就是消息的發(fā)送方只要把消息發(fā)送到應(yīng)用程序的消息隊(duì)列中去就行了,它可以馬上返回去處理別的事情,而不需要等待消息的接收方去處理完這個(gè)消息才返回,這樣就可以提高系統(tǒng)的并發(fā)性。實(shí)質(zhì)上,這就是一種異步處理機(jī)制。
?? ? ? ?這樣說(shuō)可能還是比較籠統(tǒng),我們以Android應(yīng)用程序啟動(dòng)過程源代碼分析一文中所介紹的應(yīng)用程序啟動(dòng)過程的一個(gè)片斷來(lái)具體看看是如何這種消息處理機(jī)制的。在這篇文章中,要啟動(dòng)的應(yīng)用程序稱為Activity,它的默認(rèn)Activity是MainActivity,它是由Launcher來(lái)負(fù)責(zé)啟動(dòng)的,而Launcher又是通過ActivityManagerService來(lái)啟動(dòng)的,當(dāng)ActivityManagerService為這個(gè)即將要啟的應(yīng)用程序準(zhǔn)備好新的進(jìn)程后,便通過一個(gè)Binder進(jìn)程間通信過程來(lái)通知這個(gè)新的進(jìn)程來(lái)加載MainActivity,如下圖所示:
?? ?它對(duì)應(yīng)Android應(yīng)用程序啟動(dòng)過程中的Step 30到Step 35,有興趣的讀者可以回過頭去參考Android應(yīng)用程序啟動(dòng)過程源代碼分析一文。這里的Step 30中的scheduleLaunchActivity是ActivityManagerService通過Binder進(jìn)程間通信機(jī)制發(fā)送過來(lái)的請(qǐng)求,它請(qǐng)求應(yīng)用程序中的ActivityThread執(zhí)行Step 34中的performLaunchActivity操作,即啟動(dòng)MainActivity的操作。這里我們就可以看到,Step 30的這個(gè)請(qǐng)求并沒有等待Step 34這個(gè)操作完成就返回了,它只是把這個(gè)請(qǐng)求封裝成一個(gè)消息,然后通過Step 31中的queueOrSendMessage操作把這個(gè)消息放到應(yīng)用程序的消息隊(duì)列中,然后就返回了。應(yīng)用程序發(fā)現(xiàn)消息隊(duì)列中有消息時(shí),就會(huì)通過Step 32中的handleMessage操作來(lái)處理這個(gè)消息,即調(diào)用Step 33中的handleLaunchActivity來(lái)執(zhí)行實(shí)際的加載MainAcitivy類的操作。
?? ? ? ?了解Android應(yīng)用程序的消息處理過程之后,我們就開始分樣它的實(shí)現(xiàn)原理了。與Windows應(yīng)用程序的消息處理過程一樣,Android應(yīng)用程序的消息處理機(jī)制也是由消息循環(huán)、消息發(fā)送和消息處理這三個(gè)部分組成的,接下來(lái),我們就詳細(xì)描述這三個(gè)過程。
?? ? ? ?1. 消息循環(huán)
?? ? ? ?在消息處理機(jī)制中,消息都是存放在一個(gè)消息隊(duì)列中去,而應(yīng)用程序的主線程就是圍繞這個(gè)消息隊(duì)列進(jìn)入一個(gè)無(wú)限循環(huán)的,直到應(yīng)用程序退出。如果隊(duì)列中有消息,應(yīng)用程序的主線程就會(huì)把它取出來(lái),并分發(fā)給相應(yīng)的Handler進(jìn)行處理;如果隊(duì)列中沒有消息,應(yīng)用程序的主線程就會(huì)進(jìn)入空閑等待狀態(tài),等待下一個(gè)消息的到來(lái)。在Android應(yīng)用程序中,這個(gè)消息循環(huán)過程是由Looper類來(lái)實(shí)現(xiàn)的,它定義在frameworks/base/core/java/android/os/Looper.java文件中,在分析這個(gè)類之前,我們先看一下Android應(yīng)用程序主線程是如何進(jìn)入到這個(gè)消息循環(huán)中去的。
?? ? ? ?在Android應(yīng)用程序進(jìn)程啟動(dòng)過程的源代碼分析一文中,我們分析了Android應(yīng)用程序進(jìn)程的啟動(dòng)過程,Android應(yīng)用程序進(jìn)程在啟動(dòng)的時(shí)候,會(huì)在進(jìn)程中加載ActivityThread類,并且執(zhí)行這個(gè)類的main函數(shù),應(yīng)用程序的消息循環(huán)過程就是在這個(gè)main函數(shù)里面實(shí)現(xiàn)的,我們來(lái)看看這個(gè)函數(shù)的實(shí)現(xiàn),它定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:
? ? ? ?這個(gè)函數(shù)做了兩件事情,一是在主線程中創(chuàng)建了一個(gè)ActivityThread實(shí)例,二是通過Looper類使主線程進(jìn)入消息循環(huán)中,這里我們只關(guān)注后者。
?
?? ? ? ?首先看Looper.prepareMainLooper函數(shù)的實(shí)現(xiàn),這是一個(gè)靜態(tài)成員函數(shù),定義在frameworks/base/core/java/android/os/Looper.java文件中:
? ? ? ? 函數(shù)prepareMainLooper做的事情其實(shí)就是在線程中創(chuàng)建一個(gè)Looper對(duì)象,這個(gè)Looper對(duì)象是存放在sThreadLocal成員變量里面的,成員變量sThreadLocal的類型為ThreadLocal,表示這是一個(gè)線程局部變量,即保證每一個(gè)調(diào)用了prepareMainLooper函數(shù)的線程里面都有一個(gè)獨(dú)立的Looper對(duì)象。在線程是創(chuàng)建Looper對(duì)象的工作是由prepare函數(shù)來(lái)完成的,而在創(chuàng)建Looper對(duì)象的時(shí)候,會(huì)同時(shí)創(chuàng)建一個(gè)消息隊(duì)列MessageQueue,保存在Looper的成員變量mQueue中,后續(xù)消息就是存放在這個(gè)隊(duì)列中去。消息隊(duì)列在Android應(yīng)用程序消息處理機(jī)制中最重要的組件,因此,我們看看它的創(chuàng)建過程,即它的構(gòu)造函數(shù)的實(shí)現(xiàn),實(shí)現(xiàn)frameworks/base/core/java/android/os/MessageQueue.java文件中:
?? ?它的初始化工作都交給JNI方法nativeInit來(lái)實(shí)現(xiàn)了,這個(gè)JNI方法定義在frameworks/base/core/jni/android_os_MessageQueue.cpp文件中:
?? ?在JNI中,也相應(yīng)地創(chuàng)建了一個(gè)消息隊(duì)列NativeMessageQueue,NativeMessageQueue類也是定義在frameworks/base/core/jni/android_os_MessageQueue.cpp文件中,它的創(chuàng)建過程如下所示:
? ?它主要就是在內(nèi)部創(chuàng)建了一個(gè)Looper對(duì)象,注意,這個(gè)Looper對(duì)象是實(shí)現(xiàn)在JNI層的,它與上面Java層中的Looper是不一樣的,不過它們是對(duì)應(yīng)的,下面我們進(jìn)一步分析消息循環(huán)的過程的時(shí)候,讀者就會(huì)清楚地了解到它們之間的關(guān)系。
?
?? ? ? ?這個(gè)Looper的創(chuàng)建過程也很重要,不過我們暫時(shí)放一放,先分析完android_os_MessageQueue_nativeInit函數(shù)的執(zhí)行,它創(chuàng)建了本地消息隊(duì)列NativeMessageQueue對(duì)象之后,接著調(diào)用android_os_MessageQueue_setNativeMessageQueue函數(shù)來(lái)把這個(gè)消息隊(duì)列對(duì)象保存在前面我們?cè)贘ava層中創(chuàng)建的MessageQueue對(duì)象的mPtr成員變量里面:
?? ?這里傳進(jìn)來(lái)的參數(shù)messageQueueObj即為我們前面在Java層創(chuàng)建的消息隊(duì)列對(duì)象,而gMessageQueueClassInfo.mPtr即表示在Java類MessageQueue中,其成員變量mPtr的偏移量,通過這個(gè)偏移量,就可以把這個(gè)本地消息隊(duì)列對(duì)象natvieMessageQueue保存在Java層創(chuàng)建的消息隊(duì)列對(duì)象的mPtr成員變量中,這是為了后續(xù)我們調(diào)用Java層的消息隊(duì)列對(duì)象的其它成員函數(shù)進(jìn)入到JNI層時(shí),能夠方便地找回它在JNI層所對(duì)應(yīng)的消息隊(duì)列對(duì)象。
轉(zhuǎn)載于:https://blog.51cto.com/shyluo/966586
總結(jié)
以上是生活随笔為你收集整理的Android应用程序消息处理机制(Looper、Handler)分析(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不同配置决定不同的复制的流程
- 下一篇: CommandArgument传多个值到