日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android应用程序消息处理机制(Looper、Handler)分析

發(fā)布時(shí)間:2023/12/20 Android 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android应用程序消息处理机制(Looper、Handler)分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章轉(zhuǎn)載至CSDN社區(qū)羅升陽(yáng)的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6817933

Android應(yīng)用程序是通過(guò)消息來(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)了通過(guò)消息來(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)過(guò)程源代碼分析和Android應(yīng)用程序內(nèi)部啟動(dòng)Activity過(guò)程(startActivity)的源代碼分析)、Service啟動(dòng)(Android系統(tǒng)在新進(jìn)程中啟動(dòng)自定義服務(wù)過(guò)程(startService)的原理分析和Android應(yīng)用程序綁定服務(wù)(bindService)的過(guò)程源代碼分析)以及廣播發(fā)送(Android應(yīng)用程序發(fā)送廣播(sendBroadcast)的過(guò)程分析)時(shí),它們都有一個(gè)共同的特點(diǎn),當(dāng)ActivityManagerService需要與應(yīng)用程序進(jìn)行并互時(shí),如加載Activity和Service、處理廣播待,會(huì)通過(guò)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ì)列中去,然后再 通過(guò)消息循環(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)過(guò)程源代碼分析一文中所介紹的應(yīng)用程序啟動(dòng)過(guò)程的一個(gè)片斷來(lái)具體看看是如何這種消息處理機(jī)制的。在這篇文章中,要啟動(dòng)的應(yīng)用程序稱為Activity,它的默認(rèn)Activity是MainActivity,它是由Launcher來(lái)負(fù)責(zé)啟動(dòng)的,而Launcher又是通過(guò)ActivityManagerService來(lái)啟動(dòng)的,當(dāng)ActivityManagerService為這個(gè)即將要啟的應(yīng)用程序準(zhǔn)備好新的進(jìn)程后,便通過(guò)一個(gè)Binder進(jìn)程間通信過(guò)程來(lái)通知這個(gè)新的進(jìn)程來(lái)加載MainActivity,如下圖所示:

?? ? ? ?它對(duì)應(yīng)Android應(yīng)用程序啟動(dòng)過(guò)程中的Step 30到Step 35,有興趣的讀者可以回過(guò)頭去參考Android應(yīng)用程序啟動(dòng)過(guò)程源代碼分析一文。這里的Step 30中的scheduleLaunchActivity是ActivityManagerService通過(guò)Binder進(jìn)程間通信機(jī)制發(fā) 送過(guò)來(lái)的請(qǐng)求,它請(qǐng)求應(yīng)用程序中的ActivityThread執(zhí)行Step 34中的performLaunchActivity操作,即啟動(dòng)MainActivity的操作。這里我們就可以看到,Step 30的這個(gè)請(qǐng)求并沒(méi)有等待Step 34這個(gè)操作完成就返回了,它只是把這個(gè)請(qǐng)求封裝成一個(gè)消息,然后通過(guò)Step 31中的queueOrSendMessage操作把這個(gè)消息放到應(yīng)用程序的消息隊(duì)列中,然后就返回了。應(yīng)用程序發(fā)現(xiàn)消息隊(duì)列中有消息時(shí),就會(huì)通過(guò) Step 32中的handleMessage操作來(lái)處理這個(gè)消息,即調(diào)用Step 33中的handleLaunchActivity來(lái)執(zhí)行實(shí)際的加載MainAcitivy類的操作。

?? ? ? ?了解Android應(yīng)用程序的消息處理過(guò)程之后,我們就開(kāi)始分樣它的實(shí)現(xiàn)原理了。與Windows應(yīng)用程序的消息處理過(guò)程一樣,Android應(yīng)用程序 的消息處理機(jī)制也是由消息循環(huán)、消息發(fā)送和消息處理這三個(gè)部分組成的,接下來(lái),我們就詳細(xì)描述這三個(gè)過(guò)程。

?? ? ? ?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ì)列中沒(méi)有消息,應(yīng)用程序的主線程就會(huì)進(jìn)入空閑等待狀態(tài),等待下一個(gè)消 息的到來(lái)。在Android應(yīng)用程序中,這個(gè)消息循環(huán)過(guò)程是由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)過(guò)程的源代碼分析一 文中,我們分析了Android應(yīng)用程序進(jìn)程的啟動(dòng)過(guò)程,Android應(yīng)用程序進(jìn)程在啟動(dòng)的時(shí)候,會(huì)在進(jìn)程中加載ActivityThread類,并且 執(zhí)行這個(gè)類的main函數(shù),應(yīng)用程序的消息循環(huán)過(guò)程就是在這個(gè)main函數(shù)里面實(shí)現(xiàn)的,我們來(lái)看看這個(gè)函數(shù)的實(shí)現(xiàn),它定義在 frameworks/base/core/java/android/app/ActivityThread.java文件中:

[java] view plaincopy
  • public?final?class?ActivityThread?{??
  • ????......??
  • ??
  • ????public?static?final?void?main(String[]?args)?{??
  • ????????......??
  • ??
  • ????????Looper.prepareMainLooper();??
  • ??
  • ????????......??
  • ??
  • ????????ActivityThread?thread?=?new?ActivityThread();??
  • ????????thread.attach(false);??
  • ??????????
  • ????????......??
  • ??
  • ????????Looper.loop();??
  • ??
  • ????????......??
  • ??
  • ????????thread.detach();??
  • ??
  • ????????......??
  • ????}??
  • }??
  • ?? ? ? ?這個(gè)函數(shù)做了兩件事情,一是在主線程中創(chuàng)建了一個(gè)ActivityThread實(shí)例,二是通過(guò)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文件中:

    [java] view plaincopy
  • public?class?Looper?{??
  • ????......??
  • ??
  • ????private?static?final?ThreadLocal?sThreadLocal?=?new?ThreadLocal();??
  • ??
  • ????final?MessageQueue?mQueue;??
  • ??
  • ????......??
  • ??
  • ????/**?Initialize?the?current?thread?as?a?looper.?
  • ????*?This?gives?you?a?chance?to?create?handlers?that?then?reference?
  • ????*?this?looper,?before?actually?starting?the?loop.?Be?sure?to?call?
  • ????*?{@link?#loop()}?after?calling?this?method,?and?end?it?by?calling?
  • ????*?{@link?#quit()}.?
  • ????*/??
  • ????public?static?final?void?prepare()?{??
  • ????????if?(sThreadLocal.get()?!=?null)?{??
  • ????????????throw?new?RuntimeException("Only?one?Looper?may?be?created?per?thread");??
  • ????????}??
  • ????????sThreadLocal.set(new?Looper());??
  • ????}??
  • ??
  • ????/**?Initialize?the?current?thread?as?a?looper,?marking?it?as?an?application's?main??
  • ????*??looper.?The?main?looper?for?your?application?is?created?by?the?Android?environment,?
  • ????*??so?you?should?never?need?to?call?this?function?yourself.?
  • ????*?{@link?#prepare()}?
  • ????*/??
  • ??
  • ????public?static?final?void?prepareMainLooper()?{??
  • ????????prepare();??
  • ????????setMainLooper(myLooper());??
  • ????????if?(Process.supportsProcesses())?{??
  • ????????????myLooper().mQueue.mQuitAllowed?=?false;??
  • ????????}??
  • ????}??
  • ??
  • ????private?synchronized?static?void?setMainLooper(Looper?looper)?{??
  • ????????mMainLooper?=?looper;??
  • ????}??
  • ??
  • ????/**?
  • ????*?Return?the?Looper?object?associated?with?the?current?thread.??Returns?
  • ????*?null?if?the?calling?thread?is?not?associated?with?a?Looper.?
  • ????*/??
  • ????public?static?final?Looper?myLooper()?{??
  • ????????return?(Looper)sThreadLocal.get();??
  • ????}??
  • ??
  • ????private?Looper()?{??
  • ????????mQueue?=?new?MessageQueue();??
  • ????????mRun?=?true;??
  • ????????mThread?=?Thread.currentThread();??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?函數(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)建過(guò)程,即它的構(gòu)造函數(shù)的實(shí)現(xiàn),實(shí)現(xiàn) frameworks/base/core/java/android/os/MessageQueue.java文件中:

    [java] view plaincopy
  • public?class?MessageQueue?{??
  • ????......??
  • ??
  • ????private?int?mPtr;?//?used?by?native?code??
  • ??
  • ????private?native?void?nativeInit();??
  • ??
  • ????MessageQueue()?{??
  • ????????nativeInit();??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?它的初始化工作都交給JNI方法nativeInit來(lái)實(shí)現(xiàn)了,這個(gè)JNI方法定義在frameworks/base/core/jni/android_os_MessageQueue.cpp文件中:

    [cpp] view plaincopy
  • static?void?android_os_MessageQueue_nativeInit(JNIEnv*?env,?jobject?obj)?{??
  • ????NativeMessageQueue*?nativeMessageQueue?=?new?NativeMessageQueue();??
  • ????if?(!?nativeMessageQueue)?{??
  • ????????jniThrowRuntimeException(env,?"Unable?to?allocate?native?queue");??
  • ????????return;??
  • ????}??
  • ??
  • ????android_os_MessageQueue_setNativeMessageQueue(env,?obj,?nativeMessageQueue);??
  • }??
  • ?? ? ? ?在JNI中,也相應(yīng)地創(chuàng)建了一個(gè)消息隊(duì)列NativeMessageQueue,NativeMessageQueue類也是定義在 frameworks/base/core/jni/android_os_MessageQueue.cpp文件中,它的創(chuàng)建過(guò)程如下所示:

    [cpp] view plaincopy
  • NativeMessageQueue::NativeMessageQueue()?{??
  • ????mLooper?=?Looper::getForThread();??
  • ????if?(mLooper?==?NULL)?{??
  • ????????mLooper?=?new?Looper(false);??
  • ????????Looper::setForThread(mLooper);??
  • ????}??
  • }??
  • ?? ? ? ?它主要就是在內(nèi)部創(chuàng)建了一個(gè)Looper對(duì)象,注意,這個(gè)Looper對(duì)象是實(shí)現(xiàn)在JNI層的,它與上面Java層中的Looper是不一樣的,不過(guò)它們是對(duì)應(yīng)的,下面我們進(jìn)一步分析消息循環(huán)的過(guò)程的時(shí)候,讀者就會(huì)清楚地了解到它們之間的關(guān)系。

    ?? ? ? ?這個(gè)Looper的創(chuàng)建過(guò)程也很重要,不過(guò)我們暫時(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成員變量里面:

    [cpp] view plaincopy
  • static?void?android_os_MessageQueue_setNativeMessageQueue(JNIEnv*?env,?jobject?messageQueueObj,??
  • ????????NativeMessageQueue*?nativeMessageQueue)?{??
  • ????env->SetIntField(messageQueueObj,?gMessageQueueClassInfo.mPtr,??
  • ?????????????reinterpret_cast<jint>(nativeMessageQueue));??
  • }??
  • ?? ? ? ?這里傳進(jìn)來(lái)的參數(shù)messageQueueObj即為我們前面在Java層創(chuàng)建的消息隊(duì)列對(duì)象,而 gMessageQueueClassInfo.mPtr即表示在Java類MessageQueue中,其成員變量mPtr的偏移量,通過(guò)這個(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ì)象。

    ?? ? ? ?我們?cè)倩氐絅ativeMessageQueue的構(gòu)造函數(shù)中,看看JNI層的Looper對(duì)象的創(chuàng)建過(guò)程,即看看它的構(gòu)造函數(shù)是如何實(shí)現(xiàn)的,這個(gè)Looper類實(shí)現(xiàn)在frameworks/base/libs/utils/Looper.cpp文件中:

    [cpp] view plaincopy
  • Looper::Looper(bool?allowNonCallbacks)?:??
  • ????mAllowNonCallbacks(allowNonCallbacks),??
  • ????mResponseIndex(0)?{??
  • ????int?wakeFds[2];??
  • ????int?result?=?pipe(wakeFds);??
  • ????......??
  • ??
  • ????mWakeReadPipeFd?=?wakeFds[0];??
  • ????mWakeWritePipeFd?=?wakeFds[1];??
  • ??
  • ????......??
  • ??
  • #ifdef?LOOPER_USES_EPOLL??
  • ????//?Allocate?the?epoll?instance?and?register?the?wake?pipe.??
  • ????mEpollFd?=?epoll_create(EPOLL_SIZE_HINT);??
  • ????......??
  • ??
  • ????struct?epoll_event?eventItem;??
  • ????memset(&?eventItem,?0,?sizeof(epoll_event));?//?zero?out?unused?members?of?data?field?union??
  • ????eventItem.events?=?EPOLLIN;??
  • ????eventItem.data.fd?=?mWakeReadPipeFd;??
  • ????result?=?epoll_ctl(mEpollFd,?EPOLL_CTL_ADD,?mWakeReadPipeFd,?&?eventItem);??
  • ????......??
  • #else??
  • ????......??
  • #endif??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?這個(gè)構(gòu)造函數(shù)做的事情非常重要,它跟我們后面要介紹的應(yīng)用程序主線程在消息隊(duì)列中沒(méi)有消息時(shí)要進(jìn)入等待狀態(tài)以及當(dāng)消息隊(duì)列有消息時(shí)要把應(yīng)用程序主線程喚醒的這兩個(gè)知識(shí)點(diǎn)息息相關(guān)。它主要就是通過(guò)pipe系統(tǒng)調(diào)用來(lái)創(chuàng)建了一個(gè)管道了:

    [cpp] view plaincopy
  • int?wakeFds[2];??
  • int?result?=?pipe(wakeFds);??
  • ......??
  • ??
  • mWakeReadPipeFd?=?wakeFds[0];??
  • mWakeWritePipeFd?=?wakeFds[1];??
  • ?? ? ? ?管道是Linux系統(tǒng)中的一種進(jìn)程間通信機(jī)制,具體可以參考前面一篇文章Android學(xué)習(xí)啟動(dòng)篇推 薦的一本書《Linux內(nèi)核源代碼情景分析》中的第6章--傳統(tǒng)的Uinx進(jìn)程間通信。簡(jiǎn)單來(lái)說(shuō),管道就是一個(gè)文件,在管道的兩端,分別是兩個(gè)打開(kāi)文件文 件描述符,這兩個(gè)打開(kāi)文件描述符都是對(duì)應(yīng)同一個(gè)文件,其中一個(gè)是用來(lái)讀的,別一個(gè)是用來(lái)寫的,一般的使用方式就是,一個(gè)線程通過(guò)讀文件描述符中來(lái)讀管道的 內(nèi)容,當(dāng)管道沒(méi)有內(nèi)容時(shí),這個(gè)線程就會(huì)進(jìn)入等待狀態(tài),而另外一個(gè)線程通過(guò)寫文件描述符來(lái)向管道中寫入內(nèi)容,寫入內(nèi)容的時(shí)候,如果另一端正有線程正在等待管 道中的內(nèi)容,那么這個(gè)線程就會(huì)被喚醒。這個(gè)等待和喚醒的操作是如何進(jìn)行的呢,這就要借助Linux系統(tǒng)中的epoll機(jī)制了。?Linux系統(tǒng)中的 epoll機(jī)制為處理大批量句柄而作了改進(jìn)的poll,是Linux下多路復(fù)用IO接口select/poll的增強(qiáng)版本,它能顯著減少程序在大量并發(fā)連 接中只有少量活躍的情況下的系統(tǒng)CPU利用率。但是這里我們其實(shí)只需要監(jiān)控的IO接口只有mWakeReadPipeFd一個(gè),即前面我們所創(chuàng)建的管道的 讀端,為什么還需要用到epoll呢?有點(diǎn)用牛刀來(lái)殺雞的味道。其實(shí)不然,這個(gè)Looper類是非常強(qiáng)大的,它除了監(jiān)控內(nèi)部所創(chuàng)建的管道接口之外,還提供 了addFd接口供外界面調(diào)用,外界可以通過(guò)這個(gè)接口把自己想要監(jiān)控的IO事件一并加入到這個(gè)Looper對(duì)象中去,當(dāng)所有這些被監(jiān)控的IO接口上面有事 件發(fā)生時(shí),就會(huì)喚醒相應(yīng)的線程來(lái)處理,不過(guò)這里我們只關(guān)心剛才所創(chuàng)建的管道的IO事件的發(fā)生。

    ?? ? ? ?要使用Linux系統(tǒng)的epoll機(jī)制,首先要通過(guò)epoll_create來(lái)創(chuàng)建一個(gè)epoll專用的文件描述符:

    [cpp] view plaincopy
  • mEpollFd?=?epoll_create(EPOLL_SIZE_HINT);??
  • ?? ? ? 傳入的參數(shù)EPOLL_SIZE_HINT是在這個(gè)mEpollFd上能監(jiān)控的最大文件描述符數(shù)。

    ?? ? ? 接著還要通過(guò)epoll_ctl函數(shù)來(lái)告訴epoll要監(jiān)控相應(yīng)的文件描述符的什么事件:

    [cpp] view plaincopy
  • struct?epoll_event?eventItem;??
  • memset(&?eventItem,?0,?sizeof(epoll_event));?//?zero?out?unused?members?of?data?field?union??
  • eventItem.events?=?EPOLLIN;??
  • eventItem.data.fd?=?mWakeReadPipeFd;??
  • result?=?epoll_ctl(mEpollFd,?EPOLL_CTL_ADD,?mWakeReadPipeFd,?&?eventItem);??
  • ?? ? ? 這里就是告訴mEpollFd,它要監(jiān)控mWakeReadPipeFd文件描述符的EPOLLIN事件,即當(dāng)管道中有內(nèi)容可讀時(shí),就喚醒當(dāng)前正在等待管道中的內(nèi)容的線程。
    ?? ? ? C++層的這個(gè)Looper對(duì)象創(chuàng)建好了之后,就返回到JNI層的NativeMessageQueue的構(gòu)造函數(shù),最后就返回到Java層的消息隊(duì)列 MessageQueue的創(chuàng)建過(guò)程,這樣,Java層的Looper對(duì)象就準(zhǔn)備好了。有點(diǎn)復(fù)雜,我們先小結(jié)一下這一步都做了些什么事情:

    ?? ? ? A. 在Java層,創(chuàng)建了一個(gè)Looper對(duì)象,這個(gè)Looper對(duì)象是用來(lái)進(jìn)入消息循環(huán)的,它的內(nèi)部有一個(gè)消息隊(duì)列MessageQueue對(duì)象mQueue;

    ?? ? ? B. 在JNI層,創(chuàng)建了一個(gè)NativeMessageQueue對(duì)象,這個(gè)NativeMessageQueue對(duì)象保存在Java層的消息隊(duì)列對(duì)象mQueue的成員變量mPtr中;

    ?? ? ? C. 在C++層,創(chuàng)建了一個(gè)Looper對(duì)象,保存在JNI層的NativeMessageQueue對(duì)象的成員變量mLooper中,這個(gè)對(duì)象的作用是,當(dāng) Java層的消息隊(duì)列中沒(méi)有消息時(shí),就使Android應(yīng)用程序主線程進(jìn)入等待狀態(tài),而當(dāng)Java層的消息隊(duì)列中來(lái)了新的消息后,就喚醒Android應(yīng) 用程序的主線程來(lái)處理這個(gè)消息。

    ?? ? ? 回到ActivityThread類的main函數(shù)中,在上面這些工作都準(zhǔn)備好之后,就調(diào)用Looper類的loop函數(shù)進(jìn)入到消息循環(huán)中去了:

    [cpp] view plaincopy
  • public?class?Looper?{??
  • ????......??
  • ??
  • ????public?static?final?void?loop()?{??
  • ????????Looper?me?=?myLooper();??
  • ????????MessageQueue?queue?=?me.mQueue;??
  • ??
  • ????????......??
  • ??
  • ????????while?(true)?{??
  • ????????????Message?msg?=?queue.next();?//?might?block??
  • ????????????......??
  • ??
  • ????????????if?(msg?!=?null)?{??
  • ????????????????if?(msg.target?==?null)?{??
  • ????????????????????//?No?target?is?a?magic?identifier?for?the?quit?message.??
  • ????????????????????return;??
  • ????????????????}??
  • ??
  • ????????????????......??
  • ??
  • ????????????????msg.target.dispatchMessage(msg);??
  • ??????????????????
  • ????????????????......??
  • ??
  • ????????????????msg.recycle();??
  • ????????????}??
  • ????????}??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?這里就是進(jìn)入到消息循環(huán)中去了,它不斷地從消息隊(duì)列mQueue中去獲取下一個(gè)要處理的消息msg,如果消息的target成員變量為null,就表示 要退出消息循環(huán)了,否則的話就要調(diào)用這個(gè)target對(duì)象的dispatchMessage成員函數(shù)來(lái)處理這個(gè)消息,這個(gè)target對(duì)象的類型為 Handler,下面我們分析消息的發(fā)送時(shí)會(huì)看到這個(gè)消息對(duì)象msg是如設(shè)置的。

    ?? ? ? ?這個(gè)函數(shù)最關(guān)鍵的地方便是從消息隊(duì)列中獲取下一個(gè)要處理的消息了,即MessageQueue.next函數(shù),它實(shí)現(xiàn)frameworks/base/core/java/android/os/MessageQueue.java文件中:

    [java] view plaincopy
  • public?class?MessageQueue?{??
  • ????......??
  • ??
  • ????final?Message?next()?{??
  • ????????int?pendingIdleHandlerCount?=?-1;?//?-1?only?during?first?iteration??
  • ????????int?nextPollTimeoutMillis?=?0;??
  • ??
  • ????????for?(;;)?{??
  • ????????????if?(nextPollTimeoutMillis?!=?0)?{??
  • ????????????????Binder.flushPendingCommands();??
  • ????????????}??
  • ????????????nativePollOnce(mPtr,?nextPollTimeoutMillis);??
  • ??
  • ????????????synchronized?(this)?{??
  • ????????????????//?Try?to?retrieve?the?next?message.??Return?if?found.??
  • ????????????????final?long?now?=?SystemClock.uptimeMillis();??
  • ????????????????final?Message?msg?=?mMessages;??
  • ????????????????if?(msg?!=?null)?{??
  • ????????????????????final?long?when?=?msg.when;??
  • ????????????????????if?(now?>=?when)?{??
  • ????????????????????????mBlocked?=?false;??
  • ????????????????????????mMessages?=?msg.next;??
  • ????????????????????????msg.next?=?null;??
  • ????????????????????????if?(Config.LOGV)?Log.v("MessageQueue",?"Returning?message:?"?+?msg);??
  • ????????????????????????return?msg;??
  • ????????????????????}?else?{??
  • ????????????????????????nextPollTimeoutMillis?=?(int)?Math.min(when?-?now,?Integer.MAX_VALUE);??
  • ????????????????????}??
  • ????????????????}?else?{??
  • ????????????????????nextPollTimeoutMillis?=?-1;??
  • ????????????????}??
  • ??
  • ????????????????//?If?first?time,?then?get?the?number?of?idlers?to?run.??
  • ????????????????if?(pendingIdleHandlerCount?<?0)?{??
  • ????????????????????pendingIdleHandlerCount?=?mIdleHandlers.size();??
  • ????????????????}??
  • ????????????????if?(pendingIdleHandlerCount?==?0)?{??
  • ????????????????????//?No?idle?handlers?to?run.??Loop?and?wait?some?more.??
  • ????????????????????mBlocked?=?true;??
  • ????????????????????continue;??
  • ????????????????}??
  • ??
  • ????????????????if?(mPendingIdleHandlers?==?null)?{??
  • ????????????????????mPendingIdleHandlers?=?new?IdleHandler[Math.max(pendingIdleHandlerCount,?4)];??
  • ????????????????}??
  • ????????????????mPendingIdleHandlers?=?mIdleHandlers.toArray(mPendingIdleHandlers);??
  • ????????????}??
  • ??
  • ????????????//?Run?the?idle?handlers.??
  • ????????????//?We?only?ever?reach?this?code?block?during?the?first?iteration.??
  • ????????????for?(int?i?=?0;?i?<?pendingIdleHandlerCount;?i++)?{??
  • ????????????????final?IdleHandler?idler?=?mPendingIdleHandlers[i];??
  • ????????????????mPendingIdleHandlers[i]?=?null;?//?release?the?reference?to?the?handler??
  • ??
  • ????????????????boolean?keep?=?false;??
  • ????????????????try?{??
  • ????????????????????keep?=?idler.queueIdle();??
  • ????????????????}?catch?(Throwable?t)?{??
  • ????????????????????Log.wtf("MessageQueue",?"IdleHandler?threw?exception",?t);??
  • ????????????????}??
  • ??
  • ????????????????if?(!keep)?{??
  • ????????????????????synchronized?(this)?{??
  • ????????????????????????mIdleHandlers.remove(idler);??
  • ????????????????????}??
  • ????????????????}??
  • ????????????}??
  • ??
  • ????????????//?Reset?the?idle?handler?count?to?0?so?we?do?not?run?them?again.??
  • ????????????pendingIdleHandlerCount?=?0;??
  • ??
  • ????????????//?While?calling?an?idle?handler,?a?new?message?could?have?been?delivered??
  • ????????????//?so?go?back?and?look?again?for?a?pending?message?without?waiting.??
  • ????????????nextPollTimeoutMillis?=?0;??
  • ????????}??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?調(diào)用這個(gè)函數(shù)的時(shí)候,有可能會(huì)讓線程進(jìn)入等待狀態(tài)。什么情況下,線程會(huì)進(jìn)入等待狀態(tài)呢?兩種情況,一是當(dāng)消息隊(duì)列中沒(méi)有消息時(shí),它會(huì)使線程進(jìn)入等待狀 態(tài);二是消息隊(duì)列中有消息,但是消息指定了執(zhí)行的時(shí)間,而現(xiàn)在還沒(méi)有到這個(gè)時(shí)間,線程也會(huì)進(jìn)入等待狀態(tài)。消息隊(duì)列中的消息是按時(shí)間先后來(lái)排序的,后面我們 在分析消息的發(fā)送時(shí)會(huì)看到。

    ?? ? ? ?執(zhí)行下面語(yǔ)句是看看當(dāng)前消息隊(duì)列中有沒(méi)有消息:

    [java] view plaincopy
  • nativePollOnce(mPtr,?nextPollTimeoutMillis);??
  • ?? ? ? ?這是一個(gè)JNI方法,我們等一下再分析,這里傳入的參數(shù)mPtr就是指向前面我們?cè)贘NI層創(chuàng)建的NativeMessageQueue對(duì)象了,而參數(shù) nextPollTimeoutMillis則表示如果當(dāng)前消息隊(duì)列中沒(méi)有消息,它要等待的時(shí)候,for循環(huán)開(kāi)始時(shí),傳入的值為0,表示不等待。

    ?? ? ? ?當(dāng)前nativePollOnce返回后,就去看看消息隊(duì)列中有沒(méi)有消息:

    [java] view plaincopy
  • final?Message?msg?=?mMessages;??
  • if?(msg?!=?null)?{??
  • ????final?long?when?=?msg.when;??
  • ????if?(now?>=?when)?{??
  • ????????mBlocked?=?false;??
  • ????????mMessages?=?msg.next;??
  • ????????msg.next?=?null;??
  • ????????if?(Config.LOGV)?Log.v("MessageQueue",?"Returning?message:?"?+?msg);??
  • ????????return?msg;??
  • ????}?else?{??
  • ????????nextPollTimeoutMillis?=?(int)?Math.min(when?-?now,?Integer.MAX_VALUE);??
  • ????}??
  • }?else?{??
  • ????nextPollTimeoutMillis?=?-1;??
  • }??
  • ?? ? ? ?如果消息隊(duì)列中有消息,并且當(dāng)前時(shí)候大于等于消息中的執(zhí)行時(shí)間,那么就直接返回這個(gè)消息給Looper.loop消息處理,否則的話就要等待到消息的執(zhí)行時(shí)間:

    [java] view plaincopy
  • nextPollTimeoutMillis?=?(int)?Math.min(when?-?now,?Integer.MAX_VALUE);??
  • ?? ? ? ?如果消息隊(duì)列中沒(méi)有消息,那就要進(jìn)入無(wú)窮等待狀態(tài)直到有新消息了:

    [java] view plaincopy
  • nextPollTimeoutMillis?=?-1;??
  • ?? ? ? ?-1表示下次調(diào)用nativePollOnce時(shí),如果消息中沒(méi)有消息,就進(jìn)入無(wú)限等待狀態(tài)中去。

    ?? ? ? ?這里計(jì)算出來(lái)的等待時(shí)間都是在下次調(diào)用nativePollOnce時(shí)使用的。

    ?? ? ? ?這里說(shuō)的等待,是空閑等待,而不是忙等待,因此,在進(jìn)入空閑等待狀態(tài)前,如果應(yīng)用程序注冊(cè)了IdleHandler接口來(lái)處理一些事情,那么就會(huì)先執(zhí)行 這里IdleHandler,然后再進(jìn)入等待狀態(tài)。IdlerHandler是定義在MessageQueue的一個(gè)內(nèi)部類:

    [java] view plaincopy
  • public?class?MessageQueue?{??
  • ????......??
  • ??
  • ????/**?
  • ????*?Callback?interface?for?discovering?when?a?thread?is?going?to?block?
  • ????*?waiting?for?more?messages.?
  • ????*/??
  • ????public?static?interface?IdleHandler?{??
  • ????????/**?
  • ????????*?Called?when?the?message?queue?has?run?out?of?messages?and?will?now?
  • ????????*?wait?for?more.??Return?true?to?keep?your?idle?handler?active,?false?
  • ????????*?to?have?it?removed.??This?may?be?called?if?there?are?still?messages?
  • ????????*?pending?in?the?queue,?but?they?are?all?scheduled?to?be?dispatched?
  • ????????*?after?the?current?time.?
  • ????????*/??
  • ????????boolean?queueIdle();??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?它只有一個(gè)成員函數(shù)queueIdle,執(zhí)行這個(gè)函數(shù)時(shí),如果返回值為false,那么就會(huì)從應(yīng)用程序中移除這個(gè)IdleHandler,否則的話就會(huì) 在應(yīng)用程序中繼續(xù)維護(hù)著這個(gè)IdleHandler,下次空閑時(shí)仍會(huì)再執(zhí)會(huì)這個(gè)IdleHandler。MessageQueue提供了 addIdleHandler和removeIdleHandler兩注冊(cè)和刪除IdleHandler。

    ?? ? ? ?回到MessageQueue函數(shù)中,它接下來(lái)就是在進(jìn)入等待狀態(tài)前,看看有沒(méi)有IdleHandler是需要執(zhí)行的:

    [java] view plaincopy
  • //?If?first?time,?then?get?the?number?of?idlers?to?run.??
  • if?(pendingIdleHandlerCount?<?0)?{??
  • ????pendingIdleHandlerCount?=?mIdleHandlers.size();??
  • }??
  • if?(pendingIdleHandlerCount?==?0)?{??
  • ????//?No?idle?handlers?to?run.??Loop?and?wait?some?more.??
  • ????mBlocked?=?true;??
  • ????continue;??
  • }??
  • ??
  • if?(mPendingIdleHandlers?==?null)?{??
  • ????mPendingIdleHandlers?=?new?IdleHandler[Math.max(pendingIdleHandlerCount,?4)];??
  • }??
  • mPendingIdleHandlers?=?mIdleHandlers.toArray(mPendingIdleHandlers);??
  • ?? ? ? ?如果沒(méi)有,即pendingIdleHandlerCount等于0,那下面的邏輯就不執(zhí)行了,通過(guò)continue語(yǔ)句直接進(jìn)入下一次循環(huán),否則就要 把注冊(cè)在mIdleHandlers中的IdleHandler取出來(lái),放在mPendingIdleHandlers數(shù)組中去。

    ?? ? ? ?接下來(lái)就是執(zhí)行這些注冊(cè)了的IdleHanlder了:

    [java] view plaincopy
  • //?Run?the?idle?handlers.??
  • //?We?only?ever?reach?this?code?block?during?the?first?iteration.??
  • for?(int?i?=?0;?i?<?pendingIdleHandlerCount;?i++)?{??
  • ??????final?IdleHandler?idler?=?mPendingIdleHandlers[i];??
  • ??????mPendingIdleHandlers[i]?=?null;?//?release?the?reference?to?the?handler??
  • ??
  • ??????boolean?keep?=?false;??
  • ??????try?{??
  • ????????????keep?=?idler.queueIdle();??
  • ??????}?catch?(Throwable?t)?{??
  • ????????????Log.wtf("MessageQueue",?"IdleHandler?threw?exception",?t);??
  • ??????}??
  • ??
  • ??????if?(!keep)?{??
  • ????????????synchronized?(this)?{??
  • ????????????????????mIdleHandlers.remove(idler);??
  • ????????????}??
  • ??????}??
  • }??
  • ?? ? ? ? 執(zhí)行完這些IdleHandler之后,線程下次調(diào)用nativePollOnce函數(shù)時(shí),就不設(shè)置超時(shí)時(shí)間了,因?yàn)?#xff0c;很有可能在執(zhí)行 IdleHandler的時(shí)候,已經(jīng)有新的消息加入到消息隊(duì)列中去了,因此,要重置nextPollTimeoutMillis的值:

    [java] view plaincopy
  • //?While?calling?an?idle?handler,?a?new?message?could?have?been?delivered??
  • //?so?go?back?and?look?again?for?a?pending?message?without?waiting.??
  • nextPollTimeoutMillis?=?0;??
  • ?? ? ? ?分析完MessageQueue的這個(gè)next函數(shù)之后,我們就要深入分析一下JNI方法nativePollOnce了,看看它是如何進(jìn)入等待狀態(tài) 的,這個(gè)函數(shù)定義在frameworks/base/core/jni/android_os_MessageQueue.cpp文件中:

    [cpp] view plaincopy
  • static?void?android_os_MessageQueue_nativePollOnce(JNIEnv*?env,?jobject?obj,??
  • ????????jint?ptr,?jint?timeoutMillis)?{??
  • ????NativeMessageQueue*?nativeMessageQueue?=?reinterpret_cast<NativeMessageQueue*>(ptr);??
  • ????nativeMessageQueue->pollOnce(timeoutMillis);??
  • }??
  • ?? ? ? ?這個(gè)函數(shù)首先是通過(guò)傳進(jìn)入的參數(shù)ptr取回前面在Java層創(chuàng)建MessageQueue對(duì)象時(shí)在JNI層創(chuàng)建的NatvieMessageQueue對(duì)象,然后調(diào)用它的pollOnce函數(shù):

    [cpp] view plaincopy
  • void?NativeMessageQueue::pollOnce(int?timeoutMillis)?{??
  • ????mLooper->pollOnce(timeoutMillis);??
  • }??
  • ?? ? ? ?這里將操作轉(zhuǎn)發(fā)給mLooper對(duì)象的pollOnce函數(shù)處理,這里的mLooper對(duì)象是在C++層的對(duì)象,它也是在前面在JNI層創(chuàng)建的 NatvieMessageQueue對(duì)象時(shí)創(chuàng)建的,它的pollOnce函數(shù)定義在frameworks/base/libs/utils /Looper.cpp文件中:

    [cpp] view plaincopy
  • int?Looper::pollOnce(int?timeoutMillis,?int*?outFd,?int*?outEvents,?void**?outData)?{??
  • ????int?result?=?0;??
  • ????for?(;;)?{??
  • ????????......??
  • ??
  • ????????if?(result?!=?0)?{??
  • ????????????......??
  • ??
  • ????????????return?result;??
  • ????????}??
  • ??
  • ????????result?=?pollInner(timeoutMillis);??
  • ????}??
  • }??
  • ?? ? ? ?為了方便討論,我們把這個(gè)函數(shù)的無(wú)關(guān)部分都去掉,它主要就是調(diào)用pollInner函數(shù)來(lái)進(jìn)一步操作,如果pollInner返回值不等于0,這個(gè)函數(shù)就可以返回了。

    ?? ? ? ?函數(shù)pollInner的定義如下:

    [cpp] view plaincopy
  • int?Looper::pollInner(int?timeoutMillis)?{??
  • ????......??
  • ??
  • ????int?result?=?ALOOPER_POLL_WAKE;??
  • ??
  • ????......??
  • ??
  • #ifdef?LOOPER_USES_EPOLL??
  • ????struct?epoll_event?eventItems[EPOLL_MAX_EVENTS];??
  • ????int?eventCount?=?epoll_wait(mEpollFd,?eventItems,?EPOLL_MAX_EVENTS,?timeoutMillis);??
  • ????bool?acquiredLock?=?false;??
  • #else??
  • ????......??
  • #endif??
  • ??
  • ????if?(eventCount?<?0)?{??
  • ????????if?(errno?==?EINTR)?{??
  • ????????????goto?Done;??
  • ????????}??
  • ??
  • ????????LOGW("Poll?failed?with?an?unexpected?error,?errno=%d",?errno);??
  • ????????result?=?ALOOPER_POLL_ERROR;??
  • ????????goto?Done;??
  • ????}??
  • ??
  • ????if?(eventCount?==?0)?{??
  • ????????......??
  • ????????result?=?ALOOPER_POLL_TIMEOUT;??
  • ????????goto?Done;??
  • ????}??
  • ??
  • ????......??
  • ??
  • #ifdef?LOOPER_USES_EPOLL??
  • ????for?(int?i?=?0;?i?<?eventCount;?i++)?{??
  • ????????int?fd?=?eventItems[i].data.fd;??
  • ????????uint32_t?epollEvents?=?eventItems[i].events;??
  • ????????if?(fd?==?mWakeReadPipeFd)?{??
  • ????????????if?(epollEvents?&?EPOLLIN)?{??
  • ????????????????awoken();??
  • ????????????}?else?{??
  • ????????????????LOGW("Ignoring?unexpected?epoll?events?0x%x?on?wake?read?pipe.",?epollEvents);??
  • ????????????}??
  • ????????}?else?{??
  • ????????????......??
  • ????????}??
  • ????}??
  • ????if?(acquiredLock)?{??
  • ????????mLock.unlock();??
  • ????}??
  • Done:?;??
  • #else??
  • ????......??
  • #endif??
  • ??
  • ????......??
  • ??
  • ????return?result;??
  • }??
  • ?? ? ? ?這里,首先是調(diào)用epoll_wait函數(shù)來(lái)看看epoll專用文件描述符mEpollFd所監(jiān)控的文件描述符是否有IO事件發(fā)生,它設(shè)置監(jiān)控的超時(shí)時(shí)間為timeoutMillis:

    [cpp] view plaincopy
  • int?eventCount?=?epoll_wait(mEpollFd,?eventItems,?EPOLL_MAX_EVENTS,?timeoutMillis);??
  • ?? ? ? ?回憶一下前面的Looper的構(gòu)造函數(shù),我們?cè)诶锩嬖O(shè)置了要監(jiān)控mWakeReadPipeFd文件描述符的EPOLLIN事件。

    ?? ? ? ?當(dāng)mEpollFd所監(jiān)控的文件描述符發(fā)生了要監(jiān)控的IO事件后或者監(jiān)控時(shí)間超時(shí)后,線程就從epoll_wait返回了,否則線程就會(huì)在epoll_wait函數(shù)中進(jìn)入睡眠狀態(tài)了。返回后如果eventCount等于0,就說(shuō)明是超時(shí)了:

    [cpp] view plaincopy
  • if?(eventCount?==?0)?{??
  • ????......??
  • ????result?=?ALOOPER_POLL_TIMEOUT;??
  • ????goto?Done;??
  • }??
  • ?? ? ? 如果eventCount不等于0,就說(shuō)明發(fā)生要監(jiān)控的事件:

    [cpp] view plaincopy
  • for?(int?i?=?0;?i?<?eventCount;?i++)?{??
  • ????int?fd?=?eventItems[i].data.fd;??
  • ????uint32_t?epollEvents?=?eventItems[i].events;??
  • ????if?(fd?==?mWakeReadPipeFd)?{??
  • ????????if?(epollEvents?&?EPOLLIN)?{??
  • ????????????awoken();??
  • ????????}?else?{??
  • ????????????LOGW("Ignoring?unexpected?epoll?events?0x%x?on?wake?read?pipe.",?epollEvents);??
  • ????????}??
  • ????}?else?{??
  • ????????????......??
  • ????}??
  • }??
  • ?? ? ? ?這里我們只關(guān)注mWakeReadPipeFd文件描述符上的事件,如果在mWakeReadPipeFd文件描述符上發(fā)生了EPOLLIN就說(shuō)明應(yīng)用 程序中的消息隊(duì)列里面有新的消息需要處理了,接下來(lái)它就會(huì)先調(diào)用awoken函數(shù)清空管道中把內(nèi)容,以便下次再調(diào)用pollInner函數(shù)時(shí),知道自從上 次處理完消息隊(duì)列中的消息后,有沒(méi)有新的消息加進(jìn)來(lái)。

    ?? ? ? ?函數(shù)awoken的實(shí)現(xiàn)很簡(jiǎn)單,它只是把管道中的內(nèi)容都讀取出來(lái):

    [cpp] view plaincopy
  • void?Looper::awoken()?{??
  • ????......??
  • ??
  • ????char?buffer[16];??
  • ????ssize_t?nRead;??
  • ????do?{??
  • ????????nRead?=?read(mWakeReadPipeFd,?buffer,?sizeof(buffer));??
  • ????}?while?((nRead?==?-1?&&?errno?==?EINTR)?||?nRead?==?sizeof(buffer));??
  • }??
  • ?? ? ? ?因?yàn)楫?dāng)其它的線程向應(yīng)用程序的消息隊(duì)列加入新的消息時(shí),會(huì)向這個(gè)管道寫入新的內(nèi)容來(lái)通知應(yīng)用程序主線程有新的消息需要處理了,下面我們分析消息的發(fā)送的時(shí)候?qū)?huì)看到。

    ?? ? ? ?這樣,消息的循環(huán)過(guò)程就分析完了,這部分邏輯還是比較復(fù)雜的,它利用Linux系統(tǒng)中的管道(pipe)進(jìn)程間通信機(jī)制來(lái)實(shí)現(xiàn)消息的等待和處理,不過(guò),了解了這部分內(nèi)容之后,下面我們分析消息的發(fā)送和處理就簡(jiǎn)單多了。

    ?? ? ? ?2. 消息的發(fā)送
    ?? ? ? ?應(yīng)用程序的主線程準(zhǔn)備就好消息隊(duì)列并且進(jìn)入到消息循環(huán)后,其它地方就可以往這個(gè)消息隊(duì)列中發(fā)送消息了。我們繼續(xù)以文章開(kāi)始介紹的Android應(yīng)用程序啟動(dòng)過(guò)程源代碼分析一文中的應(yīng)用程序啟動(dòng)過(guò)為例,說(shuō)明應(yīng)用程序是如何把消息加入到應(yīng)用程序的消息隊(duì)列中去的。

    ?? ? ? ?在Android應(yīng)用程序啟動(dòng)過(guò)程源代碼分析這 篇文章的Step 30中,ActivityManagerService通過(guò)調(diào)用ApplicationThread類的scheduleLaunchActivity函 數(shù)通知應(yīng)用程序,它可以加載應(yīng)用程序的默認(rèn)Activity了,這個(gè)函數(shù)定義在frameworks/base/core/java/android /app/ActivityThread.java文件中:

    [java] view plaincopy
  • public?final?class?ActivityThread?{????
  • ????
  • ????......????
  • ????
  • ????private?final?class?ApplicationThread?extends?ApplicationThreadNative?{????
  • ????
  • ????????......????
  • ????
  • ????????//?we?use?token?to?identify?this?activity?without?having?to?send?the????
  • ????????//?activity?itself?back?to?the?activity?manager.?(matters?more?with?ipc)????
  • ????????public?final?void?scheduleLaunchActivity(Intent?intent,?IBinder?token,?int?ident,????
  • ????????????????ActivityInfo?info,?Bundle?state,?List<ResultInfo>?pendingResults,????
  • ????????????????List<Intent>?pendingNewIntents,?boolean?notResumed,?boolean?isForward)?{????
  • ????????????ActivityClientRecord?r?=?new?ActivityClientRecord();????
  • ????
  • ????????????r.token?=?token;????
  • ????????????r.ident?=?ident;????
  • ????????????r.intent?=?intent;????
  • ????????????r.activityInfo?=?info;????
  • ????????????r.state?=?state;????
  • ????
  • ????????????r.pendingResults?=?pendingResults;????
  • ????????????r.pendingIntents?=?pendingNewIntents;????
  • ????
  • ????????????r.startsNotResumed?=?notResumed;????
  • ????????????r.isForward?=?isForward;????
  • ????
  • ????????????queueOrSendMessage(H.LAUNCH_ACTIVITY,?r);????
  • ????????}????
  • ????
  • ????????......????
  • ????
  • ????}????
  • ????
  • ????......????
  • }????
  • ?? ? ? ?這里把相關(guān)的參數(shù)都封裝成一個(gè)ActivityClientRecord對(duì)象r,然后調(diào)用queueOrSendMessage函數(shù)來(lái)往應(yīng)用程序的消息 隊(duì)列中加入一個(gè)新的消息(H.LAUNCH_ACTIVITY),這個(gè)函數(shù)定義在frameworks/base/core/java/android /app/ActivityThread.java文件中:

    [java] view plaincopy
  • public?final?class?ActivityThread?{????
  • ????
  • ????......????
  • ????
  • ????private?final?class?ApplicationThread?extends?ApplicationThreadNative?{????
  • ????
  • ????????......????
  • ????
  • ????????//?if?the?thread?hasn't?started?yet,?we?don't?have?the?handler,?so?just????
  • ????????//?save?the?messages?until?we're?ready.????
  • ????????private?final?void?queueOrSendMessage(int?what,?Object?obj)?{????
  • ????????????queueOrSendMessage(what,?obj,?0,?0);????
  • ????????}????
  • ????
  • ????????......????
  • ????
  • ????????private?final?void?queueOrSendMessage(int?what,?Object?obj,?int?arg1,?int?arg2)?{????
  • ????????????synchronized?(this)?{????
  • ????????????????......????
  • ????????????????Message?msg?=?Message.obtain();????
  • ????????????????msg.what?=?what;????
  • ????????????????msg.obj?=?obj;????
  • ????????????????msg.arg1?=?arg1;????
  • ????????????????msg.arg2?=?arg2;????
  • ????????????????mH.sendMessage(msg);????
  • ????????????}????
  • ????????}????
  • ????
  • ????????......????
  • ????
  • ????}????
  • ????
  • ????......????
  • }????
  • ?? ? ? ?在queueOrSendMessage函數(shù)中,又進(jìn)一步把上面?zhèn)鬟M(jìn)來(lái)的參數(shù)封裝成一個(gè)Message對(duì)象msg,然后通過(guò) mH.sendMessage函數(shù)把這個(gè)消息對(duì)象msg加入到應(yīng)用程序的消息隊(duì)列中去。這里的mH是ActivityThread類的成員變量,它的類型 為H,繼承于Handler類,它定義在frameworks/base/core/java/android/app /ActivityThread.java文件中:

    [java] view plaincopy
  • public?final?class?ActivityThread?{????
  • ????
  • ????......????
  • ????
  • ????private?final?class?H?extends?Handler?{????
  • ????
  • ????????......????
  • ????
  • ????????public?void?handleMessage(Message?msg)?{????
  • ????????????......????
  • ????????????switch?(msg.what)?{??????
  • ????????????......????
  • ????????????}????
  • ????
  • ????????......????
  • ????
  • ????}????
  • ????
  • ????......????
  • }???
  • ?? ? ? ?這個(gè)H類就是通過(guò)其成員函數(shù)handleMessage函數(shù)來(lái)處理消息的了,后面我們分析消息的處理過(guò)程時(shí)會(huì)看到。
    ?? ? ? ?ActivityThread類的這個(gè)mH成員變量是什么時(shí)候創(chuàng)建的呢?我們前面在分析應(yīng)用程序的消息循環(huán)時(shí),說(shuō)到當(dāng)應(yīng)用程序進(jìn)程啟動(dòng)之后,就會(huì)加載 ActivityThread類的main函數(shù)里面,在這個(gè)main函數(shù)里面,在通過(guò)Looper類進(jìn)入消息循環(huán)之前,會(huì)在當(dāng)前進(jìn)程中創(chuàng)建一個(gè) ActivityThread實(shí)例:

    [java] view plaincopy
  • public?final?class?ActivityThread?{??
  • ????......??
  • ??
  • ????public?static?final?void?main(String[]?args)?{??
  • ????????......??
  • ??
  • ????????ActivityThread?thread?=?new?ActivityThread();??
  • ????????thread.attach(false);??
  • ??
  • ????????......??
  • ????}??
  • }??
  • ?? ? ? ?在創(chuàng)建這個(gè)實(shí)例的時(shí)候,就會(huì)同時(shí)創(chuàng)建其成員變量mH了:

    [java] view plaincopy
  • public?final?class?ActivityThread?{??
  • ????......??
  • ??
  • ????final?H?mH?=?new?H();??
  • ??
  • ????......??
  • }???
  • ?? ? ? ?前面說(shuō)過(guò),H類繼承于Handler類,因此,當(dāng)創(chuàng)建這個(gè)H對(duì)象時(shí),會(huì)調(diào)用Handler類的構(gòu)造函數(shù),這個(gè)函數(shù)定義在frameworks/base/core/java/android/os/Handler.java文件中:

    [java] view plaincopy
  • public?class?Handler?{??
  • ????......??
  • ??
  • ????public?Handler()?{??
  • ????????......??
  • ??
  • ????????mLooper?=?Looper.myLooper();??
  • ????????......??
  • ??
  • ????????mQueue?=?mLooper.mQueue;??
  • ????????......??
  • ????}??
  • ??
  • ??
  • ????final?MessageQueue?mQueue;??
  • ????final?Looper?mLooper;??
  • ????......??
  • }??
  • ?? ? ? ?在Hanlder類的構(gòu)造函數(shù)中,主要就是初始成員變量mLooper和mQueue了。這里的myLooper是Looper類的靜態(tài)成員函數(shù),通過(guò) 它來(lái)獲得一個(gè)Looper對(duì)象,這個(gè)Looper對(duì)象就是前面我們?cè)诜治鱿⒀h(huán)時(shí),在ActivityThread類的main函數(shù)中通過(guò) Looper.prepareMainLooper函數(shù)創(chuàng)建的。Looper.myLooper函數(shù)實(shí)現(xiàn)在frameworks/base/core /java/android/os/Looper.java文件中:

    [java] view plaincopy
  • public?class?Looper?{??
  • ????......??
  • ??
  • ????public?static?final?Looper?myLooper()?{??
  • ????????return?(Looper)sThreadLocal.get();??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?有了這個(gè)Looper對(duì)象后,就可以通過(guò)Looper.mQueue來(lái)訪問(wèn)應(yīng)用程序的消息隊(duì)列了。

    ?? ? ? ?有了這個(gè)Handler對(duì)象mH后,就可以通過(guò)它來(lái)往應(yīng)用程序的消息隊(duì)列中加入新的消息了。回到前面的queueOrSendMessage函數(shù)中,當(dāng) 它準(zhǔn)備好了一個(gè)Message對(duì)象msg后,就開(kāi)始調(diào)用mH.sendMessage函數(shù)來(lái)發(fā)送消息了,這個(gè)函數(shù)定義在frameworks/base /core/java/android/os/Handler.java文件中:

    [java] view plaincopy
  • public?class?Handler?{??
  • ????......??
  • ??
  • ????public?final?boolean?sendMessage(Message?msg)??
  • ????{??
  • ????????return?sendMessageDelayed(msg,?0);??
  • ????}??
  • ??
  • ????public?final?boolean?sendMessageDelayed(Message?msg,?long?delayMillis)??
  • ????{??
  • ????????if?(delayMillis?<?0)?{??
  • ????????????delayMillis?=?0;??
  • ????????}??
  • ????????return?sendMessageAtTime(msg,?SystemClock.uptimeMillis()?+?delayMillis);??
  • ????}??
  • ??
  • ????public?boolean?sendMessageAtTime(Message?msg,?long?uptimeMillis)??
  • ????{??
  • ????????boolean?sent?=?false;??
  • ????????MessageQueue?queue?=?mQueue;??
  • ????????if?(queue?!=?null)?{??
  • ????????????msg.target?=?this;??
  • ????????????sent?=?queue.enqueueMessage(msg,?uptimeMillis);??
  • ????????}??
  • ????????else?{??
  • ????????????......??
  • ????????}??
  • ????????return?sent;??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?在發(fā)送消息時(shí),是可以指定消息的處理時(shí)間的,但是通過(guò)sendMessage函數(shù)發(fā)送的消息的處理時(shí)間默認(rèn)就為當(dāng)前時(shí)間,即表示要馬上處理,因此,從 sendMessage函數(shù)中調(diào)用sendMessageDelayed函數(shù),傳入的時(shí)間參數(shù)為0,表示這個(gè)消息不要延時(shí)處理,而在 sendMessageDelayed函數(shù)中,則會(huì)先獲得當(dāng)前時(shí)間,然后加上消息要延時(shí)處理的時(shí)間,即得到這個(gè)處理這個(gè)消息的絕對(duì)時(shí)間,然后調(diào)用 sendMessageAtTime函數(shù)來(lái)把消息加入到應(yīng)用程序的消息隊(duì)列中去。

    ?? ? ? ?在sendMessageAtTime函數(shù),首先得到應(yīng)用程序的消息隊(duì)列mQueue,這是在Handler對(duì)象構(gòu)造時(shí)初始化好的,前面已經(jīng)分析過(guò)了,接著設(shè)置這個(gè)消息的目標(biāo)對(duì)象target,即這個(gè)消息最終是由誰(shuí)來(lái)處理的:

    [java] view plaincopy
  • msg.target?=?this;??
  • ?? ? ? ?這里將它賦值為this,即表示這個(gè)消息最終由這個(gè)Handler對(duì)象來(lái)處理,即由ActivityThread對(duì)象的mH成員變量來(lái)處理。

    ?? ? ? ?函數(shù)最后調(diào)用queue.enqueueMessage來(lái)把這個(gè)消息加入到應(yīng)用程序的消息隊(duì)列中去,這個(gè)函數(shù)實(shí)現(xiàn)在frameworks/base/core/java/android/os/MessageQueue.java文件中:

    [java] view plaincopy
  • public?class?MessageQueue?{??
  • ????......??
  • ??
  • ????final?boolean?enqueueMessage(Message?msg,?long?when)?{??
  • ????????......??
  • ??
  • ????????final?boolean?needWake;??
  • ????????synchronized?(this)?{??
  • ????????????......??
  • ??
  • ????????????msg.when?=?when;??
  • ????????????//Log.d("MessageQueue",?"Enqueing:?"?+?msg);??
  • ????????????Message?p?=?mMessages;??
  • ????????????if?(p?==?null?||?when?==?0?||?when?<?p.when)?{??
  • ????????????????msg.next?=?p;??
  • ????????????????mMessages?=?msg;??
  • ????????????????needWake?=?mBlocked;?//?new?head,?might?need?to?wake?up??
  • ????????????}?else?{??
  • ????????????????Message?prev?=?null;??
  • ????????????????while?(p?!=?null?&&?p.when?<=?when)?{??
  • ????????????????????prev?=?p;??
  • ????????????????????p?=?p.next;??
  • ????????????????}??
  • ????????????????msg.next?=?prev.next;??
  • ????????????????prev.next?=?msg;??
  • ????????????????needWake?=?false;?//?still?waiting?on?head,?no?need?to?wake?up??
  • ????????????}??
  • ??
  • ????????}??
  • ????????if?(needWake)?{??
  • ????????????nativeWake(mPtr);??
  • ????????}??
  • ????????return?true;??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?把消息加入到消息隊(duì)列時(shí),分兩種情況,一種當(dāng)前消息隊(duì)列為空時(shí),這時(shí)候應(yīng)用程序的主線程一般就是處于空閑等待狀態(tài)了,這時(shí)候就要喚醒它,另一種情況是應(yīng) 用程序的消息隊(duì)列不為空,這時(shí)候就不需要喚醒應(yīng)用程序的主線程了,因?yàn)檫@時(shí)候它一定是在忙著處于消息隊(duì)列中的消息,因此不會(huì)處于空閑等待的狀態(tài)。

    ?? ? ? ?第一種情況比較簡(jiǎn)單,只要把消息放在消息隊(duì)列頭就可以了:

    [java] view plaincopy
  • msg.next?=?p;??
  • mMessages?=?msg;??
  • needWake?=?mBlocked;?//?new?head,?might?need?to?wake?up??
  • ?? ? ? ?第二種情況相對(duì)就比較復(fù)雜一些了,前面我們說(shuō)過(guò),當(dāng)往消息隊(duì)列中發(fā)送消息時(shí),是可以指定消息的處理時(shí)間的,而消息隊(duì)列中的消息,就是按照這個(gè)時(shí)間從小到 大來(lái)排序的,因此,當(dāng)把新的消息加入到消息隊(duì)列時(shí),就要根據(jù)它的處理時(shí)間來(lái)找到合適的位置,然后再放進(jìn)消息隊(duì)列中去:

    [java] view plaincopy
  • Message?prev?=?null;??
  • while?(p?!=?null?&&?p.when?<=?when)?{??
  • ????prev?=?p;??
  • ????p?=?p.next;??
  • }??
  • msg.next?=?prev.next;??
  • prev.next?=?msg;??
  • needWake?=?false;?//?still?waiting?on?head,?no?need?to?wake?up??
  • ?? ? ? ?把消息加入到消息隊(duì)列去后,如果應(yīng)用程序的主線程正處于空閑等待狀態(tài),就需要調(diào)用natvieWake函數(shù)來(lái)喚醒它了,這是一個(gè)JNI方法,定義在 frameworks/base/core/jni/android_os_MessageQueue.cpp文件中:

    [java] view plaincopy
  • static?void?android_os_MessageQueue_nativeWake(JNIEnv*?env,?jobject?obj,?jint?ptr)?{??
  • ????NativeMessageQueue*?nativeMessageQueue?=?reinterpret_cast<NativeMessageQueue*>(ptr);??
  • ????return?nativeMessageQueue->wake();??
  • }??
  • ?? ? ? ?這個(gè)JNI層的NativeMessageQueue對(duì)象我們?cè)谇懊娣治鱿⒀h(huán)的時(shí)候創(chuàng)建好的,保存在Java層的MessageQueue對(duì)象的 mPtr成員變量中,這里把它取回來(lái)之后,就調(diào)用它的wake函數(shù)來(lái)喚醒應(yīng)用程序的主線程,這個(gè)函數(shù)也是定義在frameworks/base/core /jni/android_os_MessageQueue.cpp文件中:

    [java] view plaincopy
  • void?NativeMessageQueue::wake()?{??
  • ????mLooper->wake();??
  • }??
  • ?? ? ? ?這里它又通過(guò)成員變量mLooper的wake函數(shù)來(lái)執(zhí)行操作,這里的mLooper成員變量是一個(gè)C++層實(shí)現(xiàn)的Looper對(duì)象,它定義在frameworks/base/libs/utils/Looper.cpp文件中:

    [java] view plaincopy
  • void?Looper::wake()?{??
  • ????......??
  • ??
  • ????ssize_t?nWrite;??
  • ????do?{??
  • ????????nWrite?=?write(mWakeWritePipeFd,?"W",?1);??
  • ????}?while?(nWrite?==?-1?&&?errno?==?EINTR);??
  • ??
  • ????.......??
  • }??
  • ?? ? ? ?這個(gè)wake函數(shù)很簡(jiǎn)單,只是通過(guò)打開(kāi)文件描述符mWakeWritePipeFd往管道的寫入一個(gè)"W"字符串。其實(shí),往管道寫入什么內(nèi)容并不重要, 往管道寫入內(nèi)容的目的是為了喚醒應(yīng)用程序的主線程。前面我們?cè)诜治鰬?yīng)用程序的消息循環(huán)時(shí)說(shuō)到,當(dāng)應(yīng)用程序的消息隊(duì)列中沒(méi)有消息處理時(shí),應(yīng)用程序的主線程就 會(huì)進(jìn)入空閑等待狀態(tài),而這個(gè)空閑等待狀態(tài)就是通過(guò)調(diào)用這個(gè)Looper類的pollInner函數(shù)來(lái)進(jìn)入的,具體就是在pollInner函數(shù)中調(diào)用 epoll_wait函數(shù)來(lái)等待管道中有內(nèi)容可讀的。

    ?? ? ? ?這時(shí)候既然管道中有內(nèi)容可讀了,應(yīng)用程序的主線程就會(huì)從這里的Looper類的pollInner函數(shù)返回到JNI層的nativePollOnce函 數(shù),最后返回到Java層中的MessageQueue.next函數(shù)中去,這里它就會(huì)發(fā)現(xiàn)消息隊(duì)列中有新的消息需要處理了,于就會(huì)處理這個(gè)消息。

    ?? ? ? ?3. 消息的處理

    ?? ? ? ?前面在分析消息循環(huán)時(shí),說(shuō)到應(yīng)用程序的主線程是在Looper類的loop成員函數(shù)中進(jìn)行消息循環(huán)過(guò)程的,這個(gè)函數(shù)定義在frameworks/base/core/java/android/os/Looper.java文件中:

    [java] view plaincopy
  • public?class?Looper?{??
  • ????......??
  • ??
  • ????public?static?final?void?loop()?{??
  • ????????Looper?me?=?myLooper();??
  • ????????MessageQueue?queue?=?me.mQueue;??
  • ??
  • ????????......??
  • ??
  • ????????while?(true)?{??
  • ????????????Message?msg?=?queue.next();?//?might?block??
  • ????????????......??
  • ??
  • ????????????if?(msg?!=?null)?{??
  • ????????????????if?(msg.target?==?null)?{??
  • ????????????????????//?No?target?is?a?magic?identifier?for?the?quit?message.??
  • ????????????????????return;??
  • ????????????????}??
  • ??
  • ????????????????......??
  • ??
  • ????????????????msg.target.dispatchMessage(msg);??
  • ??????????????????
  • ????????????????......??
  • ??
  • ????????????????msg.recycle();??
  • ????????????}??
  • ????????}??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?它從消息隊(duì)列中獲得消息對(duì)象msg后,就會(huì)調(diào)用它的target成員變量的dispatchMessage函數(shù)來(lái)處理這個(gè)消息。在前面分析消息的發(fā)送時(shí) 說(shuō)過(guò),這個(gè)消息對(duì)象msg的成員變量target是在發(fā)送消息的時(shí)候設(shè)置好的,一般就通過(guò)哪個(gè)Handler來(lái)發(fā)送消息,就通過(guò)哪個(gè)Handler來(lái)處理 消息。

    ?? ? ? ?我們繼續(xù)以前面分析消息的發(fā)送時(shí)所舉的例子來(lái)分析消息的處理過(guò)程。前面說(shuō)到,在Android應(yīng)用程序啟動(dòng)過(guò)程源代碼分析這 篇文章的Step 30中,ActivityManagerService通過(guò)調(diào)用ApplicationThread類的scheduleLaunchActivity函 數(shù)通知應(yīng)用程序,它可以加載應(yīng)用程序的默認(rèn)Activity了,而ApplicationThread類的scheduleLaunchActivity 函數(shù)最終把這個(gè)請(qǐng)求封裝成一個(gè)消息,然后通過(guò)ActivityThread類的成員變量mH來(lái)把這個(gè)消息加入到應(yīng)用程序的消息隊(duì)列中去。現(xiàn)在要對(duì)這個(gè)消息 進(jìn)行處理了,于是就會(huì)調(diào)用H類的dispatchMessage函數(shù)進(jìn)行處理。

    ?? ? ? ?H類沒(méi)有實(shí)現(xiàn)自己的dispatchMessage函數(shù),但是它繼承了父類Handler的dispatchMessage函數(shù),這個(gè)函數(shù)定義在 frameworks/base/core/java/android/os/ Handler.java文件中:

    [java] view plaincopy
  • public?class?Handler?{??
  • ????......??
  • ??
  • ????public?void?dispatchMessage(Message?msg)?{??
  • ????????if?(msg.callback?!=?null)?{??
  • ????????????handleCallback(msg);??
  • ????????}?else?{??
  • ????????????if?(mCallback?!=?null)?{??
  • ????????????????if?(mCallback.handleMessage(msg))?{??
  • ????????????????????return;??
  • ????????????????}??
  • ????????????}??
  • ????????????handleMessage(msg);??
  • ????????}??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?這里的消息對(duì)象msg的callback成員變量和Handler類的mCallBack成員變量一般都為null,于是,就會(huì)調(diào)用Handler類的 handleMessage函數(shù)來(lái)處理這個(gè)消息,由于H類在繼承Handler類時(shí),重寫了handleMessage函數(shù),因此,這里調(diào)用的實(shí)際上是H 類的handleMessage函數(shù),這個(gè)函數(shù)定義在frameworks/base/core/java/android/app /ActivityThread.java文件中:

    [java] view plaincopy
  • public?final?class?ActivityThread?{????
  • ????
  • ????......????
  • ????
  • ????private?final?class?H?extends?Handler?{????
  • ????
  • ????????......????
  • ????
  • ????????public?void?handleMessage(Message?msg)?{????
  • ????????????......????
  • ????????????switch?(msg.what)?{????
  • ????????????case?LAUNCH_ACTIVITY:?{????
  • ????????????????ActivityClientRecord?r?=?(ActivityClientRecord)msg.obj;????
  • ????
  • ????????????????r.packageInfo?=?getPackageInfoNoCheck(????
  • ????????????????????r.activityInfo.applicationInfo);????
  • ????????????????handleLaunchActivity(r,?null);????
  • ????????????}?break;????
  • ????????????......????
  • ????????????}????
  • ????
  • ????????......????
  • ????
  • ????}????
  • ????
  • ????......????
  • }????
  • ?? ? ? ? 因?yàn)榍懊嬖诜治鱿⒌陌l(fā)送時(shí)所舉的例子中,發(fā)送的消息的類型為H.LAUNCH_ACTIVITY,因此,這里就會(huì)調(diào)用ActivityThread類的handleLaunchActivity函數(shù)來(lái)真正地處理這個(gè)消息了,后面的具體過(guò)程就可以參考Android應(yīng)用程序啟動(dòng)過(guò)程源代碼分析這篇文章了。

    ?? ? ? ? 至此,我們就從消息循環(huán)、消息發(fā)送和消息處理三個(gè)部分分析完Android應(yīng)用程序的消息處理機(jī)制了,為了更深理解,這里我們對(duì)其中的一些要點(diǎn)作一個(gè)總結(jié):

    ?? ? ? ? A. Android應(yīng)用程序的消息處理機(jī)制由消息循環(huán)、消息發(fā)送和消息處理三個(gè)部分組成的。

    ?? ? ? ? B. Android應(yīng)用程序的主線程在進(jìn)入消息循環(huán)過(guò)程前,會(huì)在內(nèi)部創(chuàng)建一個(gè)Linux管道(Pipe),這個(gè)管道的作用是使得Android應(yīng)用程序主線程 在消息隊(duì)列為空時(shí)可以進(jìn)入空閑等待狀態(tài),并且使得當(dāng)應(yīng)用程序的消息隊(duì)列有消息需要處理時(shí)喚醒應(yīng)用程序的主線程。

    ?? ? ? ? C. Android應(yīng)用程序的主線程進(jìn)入空閑等待狀態(tài)的方式實(shí)際上就是在管道的讀端等待管道中有新的內(nèi)容可讀,具體來(lái)說(shuō)就是是通過(guò)Linux系統(tǒng)的Epoll機(jī)制中的epoll_wait函數(shù)進(jìn)行的。

    ?? ? ? ? D. 當(dāng)往Android應(yīng)用程序的消息隊(duì)列中加入新的消息時(shí),會(huì)同時(shí)往管道中的寫端寫入內(nèi)容,通過(guò)這種方式就可以喚醒正在等待消息到來(lái)的應(yīng)用程序主線程。

    ?? ? ? ? E. 當(dāng)應(yīng)用程序主線程在進(jìn)入空閑等待前,會(huì)認(rèn)為當(dāng)前線程處理空閑狀態(tài),于是就會(huì)調(diào)用那些已經(jīng)注冊(cè)了的IdleHandler接口,使得應(yīng)用程序有機(jī)會(huì)在空閑的時(shí)候處理一些事情。

    老羅的新浪微博:http://weibo.com/shengyangluo,歡迎關(guān)注!

    轉(zhuǎn)載于:https://www.cnblogs.com/Free-Thinker/p/4142491.html

    總結(jié)

    以上是生活随笔為你收集整理的Android应用程序消息处理机制(Looper、Handler)分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    国产韩国日本高清视频 | 国产日韩精品在线 | 波多野结衣在线视频一区 | 国产精品久久久久久妇 | 日韩在线精品一区 | 天天干天天做 | 免费在线色 | 亚洲天堂自拍视频 | 99色在线观看视频 | 天天躁天天狠天天透 | 亚洲一区免费在线 | 亚洲欧美va | 99精品一级欧美片免费播放 | 久久久91精品国产一区二区三区 | 最新国产在线 | 日韩中文字幕免费看 | 久草视频网 | 992tv又爽又黄的免费视频 | 久久久久国产精品免费网站 | 精品视频久久 | 狠狠狠的干 | 亚洲丁香日韩 | 黄色软件视频大全免费下载 | 91超在线 | 国产精品免费一区二区三区在线观看 | 久久九九久久九九 | 在线色资源 | 精品视频免费久久久看 | 色视频在线免费观看 | 国产老太婆免费交性大片 | 黄色视屏免费在线观看 | 欧美成人精品欧美一级乱 | 色噜噜日韩精品欧美一区二区 | www黄色大片 | 国产精品九九久久久久久久 | 国产精品一区二区三区电影 | 亚洲高清视频在线观看免费 | 日韩久久久久久久久 | 超碰在线97免费 | 亚洲国产视频直播 | 久操操 | 久久第四色 | 不卡视频在线看 | 人人澡av| 亚洲精品456在线播放 | 国产视频一区二区三区在线 | 天天艹天天干天天 | 免费十分钟 | 天天操天天爽天天干 | 狠狠色丁香九九婷婷综合五月 | 91香蕉视频色版 | 国产在线日韩 | 日一日操一操 | 精品麻豆| 中文字幕av免费 | 1024手机基地在线观看 | 91原创在线观看 | 久久综合狠狠综合久久狠狠色综合 | 欧美资源在线观看 | 国产一级片一区二区三区 | 国产麻豆视频 | 国产手机在线视频 | 久久噜噜少妇网站 | 在线亚洲人成电影网站色www | 婷婷伊人综合亚洲综合网 | 国产精品美女www爽爽爽视频 | 97在线超碰 | 久久高清片 | www.91国产| 国产一区视频免费在线观看 | 亚洲欧美精品一区 | 精品一二区 | 一区二区三区四区精品 | 国产免费大片 | 免费亚洲精品视频 | 亚洲视频专区在线 | 精品久久网| 久草精品网 | 97国产精品 | 免费v片 | 免费看黄在线网站 | www.五月婷婷.com | 久久免费成人网 | 在线精品亚洲一区二区 | 久久综合九色综合欧美狠狠 | 日韩中文久久 | 91久久偷偷做嫩草影院 | 在线观看久 | 成人黄色电影在线 | 色在线国产 | 欧美91精品久久久久国产性生爱 | 亚洲久久视频 | 久久男人免费视频 | 亚洲电影影音先锋 | 青草视频在线 | 日韩av免费网站 | 国产精品一区二区在线看 | 九九在线播放 | 亚洲一区二区天堂 | 91桃花视频 | 国产手机在线播放 | 在线黄频 | 丝袜美腿一区 | 久久久久久久久久久电影 | 免费在线一区二区 | 欧美成人精品三级在线观看播放 | 国产成人精品区 | 久久国产精品一区二区 | 综合色伊人 | 精品成人在线 | 在线成人国产 | 超碰在线观看99 | 丝袜少妇在线 | 一区二区三区高清 | 亚洲国产一区在线观看 | 欧美男女爱爱视频 | 欧美日韩69| 婷婷在线色| 午夜国产一区 | 日韩 在线观看 | 国产精品第52页 | 久久久wwww | 天天爽天天碰狠狠添 | 色大片免费看 | 久久字幕网 | 一区二区三区日韩在线观看 | 国产视频日本 | 色综合天天综合在线视频 | 国产精品99久久久久久久久 | 在线最新av| 伊人资源视频在线 | 爱爱av网站| 91精品一区二区三区久久久久久 | 久久久免费精品国产一区二区 | 欧美日韩一区二区免费在线观看 | 97av视频| 91视频免费国产 | 在线中文字幕播放 | 亚洲欧洲在线视频 | 日本中文字幕在线免费观看 | 国产在线精品观看 | 91在线日韩 | 国产不卡免费av | 91av视屏 | 99国产精品免费网站 | 网站免费黄 | 免费观看av| 九九99靖品 | 色视频国产直接看 | 国产亚洲精品成人av久久影院 | 99久久精品国产网站 | 五月天亚洲综合小说网 | 99精品视频免费看 | 欧美亚洲久久 | 69久久99精品久久久久婷婷 | 久草在线综合 | 久久99热这里只有精品国产 | 日日夜夜网| 2021国产精品视频 | 国产精品片| 粉嫩av一区二区三区四区在线观看 | 九九综合久久 | 亚洲男模gay裸体gay | 亚洲精品久久久久999中文字幕 | 国产午夜精品福利视频 | 99精品美女| 在线免费色| 国产中的精品av小宝探花 | 亚洲黄色免费网站 | 免费a级毛片在线看 | 天天操操操操操操 | 欧美激情视频一区二区三区免费 | 日韩在线播放视频 | 伊人午夜视频 | 日韩av免费在线电影 | 欧美一级视频在线观看 | 国产精品私人影院 | 久久天堂亚洲 | 国产精品美女999 | 黄色网址在线播放 | 中日韩三级视频 | a黄色片在线观看 | 激情av网址| 国产成人三级在线观看 | 久久a久久 | a视频在线播放 | 99在线精品免费视频九九视 | 福利视频入口 | 欧美不卡视频在线 | 深夜成人av | 成人午夜影视 | 亚洲国产欧美在线人成大黄瓜 | 国产99区 | 欧美性极品xxxx做受 | 国产综合视频在线观看 | 91麻豆精品国产自产在线 | 亚洲天堂网视频在线观看 | 日韩在线欧美在线 | 国产午夜在线观看 | 91传媒视频在线观看 | av中文字幕av | 欧美日韩精品在线免费观看 | www黄com | 国产精品每日更新 | 国产一区二区三区视频在线 | 成人a毛片 | 日韩欧美精品在线观看 | 国产日韩欧美网站 | 日韩欧美91 | 国产欧美精品一区二区三区四区 | 天天干夜夜爽 | 激情网综合 | 精品久久久久久久久久国产 | 日韩色视频在线观看 | 欧美激情在线看 | 黄色片网站av | 91资源在线免费观看 | 亚洲精品中文在线观看 | 亚洲激情影院 | 91视频免费 | 亚洲经典视频在线观看 | 亚洲午夜久久久影院 | 久久a免费视频 | 精品久久久久久久久久久院品网 | 日本特黄特色aaa大片免费 | 亚洲一级片av | 久久不卡免费视频 | 亚洲3级 | 久久电影日韩 | 91黄色在线观看 | 久久精品国产免费 | 国产精品自产拍在线观看中文 | 丁香婷婷激情啪啪 | 狠狠躁夜夜av | 国产九九热 | av网址在线播放 | www.狠狠操| 美女黄视频免费看 | 91九色丨porny丨丰满6 | 西西大胆免费视频 | 免费av成人在线 | 亚洲午夜av久久乱码 | 四虎影视久久久 | 最近中文字幕完整高清 | 在线免费观看视频你懂的 | 人人草在线观看 | 亚洲一区二区高潮无套美女 | 日日干夜夜干 | 中文理论片 | 久精品视频 | 亚洲一区二区精品3399 | av在线免费网站 | 日韩成人免费在线观看 | 免费观看一区二区三区视频 | 一区二区 久久 | 97综合网| 久草在线高清视频 | 色婷婷激情四射 | 国产精品美女久久久久久久久久久 | 天天夜操| 亚洲一级电影在线观看 | 日韩免费小视频 | 精品国产一区二区久久 | 日韩理论在线播放 | 在线观看视频国产 | 999国产| 成年人av在线播放 | 91久久爱热色涩涩 | www.一区二区三区 | 国产精品一区二区三区在线免费观看 | 日本视频不卡 | 99视频网址 | 狠狠色狠狠色合久久伊人 | 国产精品日韩欧美 | 日本中文字幕高清 | 天天色综合三 | 亚洲黄色av一区 | 激情电影影院 | 91精品国产九九九久久久亚洲 | 国产五月| 国产精品九九九九九 | 久久激情视频网 | 日本中文字幕观看 | 国内精品视频久久 | 亚洲国产精品推荐 | 国产成在线观看免费视频 | 精品久久亚洲 | 久久久免费播放 | 中文字幕精品在线 | 午夜精品一二三区 | 免费色视频 | 国产91免费在线 | 麻豆传媒视频在线 | 这里有精品在线视频 | 欧美日韩亚洲精品在线 | 亚洲综合欧美日韩狠狠色 | 草久视频在线观看 | 欧美一区二区三区四区夜夜大片 | 人成免费网站 | www.97视频 | 美国人与动物xxxx | 五月婷网 | 亚洲 欧美变态 另类 综合 | 国产一区免费在线观看 | 国产精品免费在线 | 国产成人av在线 | 日韩中文字幕电影 | 国产精品久久99综合免费观看尤物 | 久久久影院官网 | 国产一级二级在线 | 久热国产视频 | 少妇bbb搡bbbb搡bbbb | 亚洲精品视频网站在线观看 | 国产免费片 | 久久免费视频这里只有精品 | 麻豆高清免费国产一区 | 国产99久久久精品 | 亚洲国产成人高清精品 | 婷婷成人综合 | 日韩精品一区二区三区电影 | 中文字幕日韩精品有码视频 | 91麻豆精品国产91久久久无限制版 | 色婷婷综合视频在线观看 | 日韩中文字幕网站 | 日韩久久久久久久久 | 国产色久| 亚洲高清在线精品 | 日韩在线观看你懂的 | 日韩一区二区三区在线观看 | 涩涩成人在线 | 日韩三级免费观看 | 国产亚洲一区二区在线观看 | 国产精品剧情在线亚洲 | 97综合在线| 少妇av网| 国产高清久久久久 | 在线观看中文字幕dvd播放 | 2023年中文无字幕文字 | 免费视频 你懂的 | www.狠狠操.com| av中文字幕亚洲 | 青春草免费在线视频 | 亚洲成人麻豆 | 日韩网站一区 | 91精品啪在线观看国产81旧版 | 国产视频亚洲精品 | 午夜成人免费电影 | bbbbb女女女女女bbbbb国产 | 九九九视频在线 | 91九色免费视频 | 日韩成人黄色av | 天天操人| 成 人 黄 色 免费播放 | 免费观看国产成人 | a电影在线观看 | 香蕉视频91| 日韩欧美一区二区在线播放 | 亚洲精品高清在线 | 国产成人免费精品 | 激情网综合 | 天天综合狠狠精品 | 日韩在线第一区 | 婷婷色伊人 | 这里有精品在线视频 | 国产中文字幕在线免费观看 | 久草视频在线免费看 | 在线观看免费一级片 | 综合激情伊人 | 在线观看亚洲精品 | 久久久久亚洲精品 | av电影久久 | 美女视频永久黄网站免费观看国产 | 久久免费看a级毛毛片 | 欧美天天射 | 九九热re | 久久国产精品99久久人人澡 | 婷婷色综合| 视频1区2区 | 欧美久久综合 | 久久艹艹 | 天天艹天天 | 天天操天天干天天综合网 | 久久久精品电影 | 精品在线观看国产 | 美女视频黄是免费的 | 国产午夜精品福利视频 | 丁香六月在线观看 | 成人免费xxx在线观看 | 99视频在线观看一区三区 | 欧美精品久久久久久久久久久 | 欧美成人理伦片 | 欧美特一级片 | 久久99国产精品久久 | 黄色成人av网址 | 欧美一级特黄高清视频 | 久草男人天堂 | 亚洲国产精品小视频 | 女人18精品一区二区三区 | 97成人精品区在线播放 | 黄色三级在线 | 欧美日韩国产成人 | 国产亚洲亚洲 | 狠狠干狠狠操 | 午夜av色 | 999久久久久久久久 69av视频在线观看 | 成人一级 | 成人午夜av电影 | aaa日本高清在线播放免费观看 | 麻豆视频免费入口 | 亚洲国产精品va在线看黑人 | 日韩理论影院 | 国产日产精品一区二区三区四区的观看方式 | av免费观看在线 | 在线播放日韩av | 国产一二三四在线观看视频 | 不卡电影免费在线播放一区 | 欧美少妇的秘密 | 亚洲精品在线观看不卡 | 精品一二三区视频 | 久久国产精品一区二区三区四区 | 国产91免费观看 | a级片韩国 | 草久视频在线观看 | 91久久电影 | 国产精品麻豆91 | 亚洲观看黄色网 | 人人爽人人澡人人添人人人人 | 六月丁香婷婷在线 | 国产在线欧美日韩 | 99在线免费视频观看 | 午夜国产一区 | 亚洲成aⅴ人片久久青草影院 | 成人黄色在线电影 | 国产精品成人一区二区 | 超碰个人在线 | 日韩成人精品在线观看 | 国产美女黄网站免费 | 日本中文字幕在线免费观看 | 亚洲欧洲日韩在线观看 | 久久久久久久久久影院 | 91视频免费看片 | 亚洲国产手机在线 | 99久久精品免费一区 | 日韩中文字幕免费看 | 超碰最新网址 | 九九热中文字幕 | 人人草人 | 国产精品久久久区三区天天噜 | 亚洲精品美女在线观看播放 | 日韩av不卡在线播放 | 久久久影院一区二区三区 | 亚洲欧美日韩精品久久久 | 国产丝袜高跟 | 97在线观看免费观看高清 | 开心激情综合网 | 亚洲欧美视频 | 午夜黄色一级片 | 99这里只有久久精品视频 | 四虎在线免费视频 | 久久免费的视频 | 亚洲午夜剧场 | 欧美analxxxx | 日韩大片免费观看 | 97精品电影院 | 成年人在线看片 | 97视频资源 | 怡红院av久久久久久久 | 久草精品国产 | 99免费看片 | 一级大片在线观看 | 日韩av在线资源 | 国产三级精品在线 | 国产美腿白丝袜足在线av | 国产精品色 | 在线免费av网 | 欧美在线free | 狠狠色伊人亚洲综合网站色 | 激情小说网站亚洲综合网 | 韩国av免费看 | 中国一级片视频 | 久久国产免费 | 欧美色综合天天久久综合精品 | 亚洲一级片免费观看 | 99精品视频在线观看免费 | 国产成人免费精品 | av片在线观看| 久久久久成人精品 | 久久久久久久久亚洲精品 | 天天干天天操天天射 | av中文字幕网 | 久久久久免费 | 午夜三级理论 | 91超碰免费在线 | 国产精品麻豆一区二区三区 | 992tv在线观看网站 | 色姑娘综合天天 | 国产91免费在线观看 | 久久精品国产精品亚洲 | 最新色视频 | 91av超碰| 日韩免费一级a毛片在线播放一级 | 国产美女视频一区 | 国产在线va | 亚洲在线视频网站 | 在线日韩av | www.久草.com | 国产日韩精品一区二区在线观看播放 | 一区二区三区在线免费播放 | 欧美三级在线播放 | 中文字幕美女免费在线 | 欧美日韩一区二区免费在线观看 | 婷婷中文字幕综合 | 特级西西444www高清大视频 | 久久av福利 | 天天综合网入口 | 欧美日韩国产一区二区在线观看 | 免费在线观看中文字幕 | 人人搞人人干 | 色综合天天色 | 成年人黄色免费网站 | 国产不卡在线播放 | 日日操操 | se婷婷| 操老逼免费视频 | 久久精品一区二区三区视频 | 日韩剧| 国产精品成人一区二区 | 国产98色在线 | 日韩 | 97免费在线观看视频 | 国内精品久久久久久久久久久久 | 深爱五月激情五月 | 91福利影院在线观看 | 在线免费观看欧美日韩 | 久久久久女人精品毛片 | 欧美做受高潮1 | 伊色综合久久之综合久久 | 伊人天天综合 | 成人在线网站观看 | 国产精品精 | 免费精品视频在线观看 | 亚洲成人av片在线观看 | 国产+日韩欧美 | 国产成人一区二区在线观看 | av在线电影免费观看 | 国产精品久久视频 | 国产精品 999 | 三级免费黄色 | 亚洲高清免费在线 | 国产一区二区三区 在线 | 国产又粗又猛又色 | 国产97超碰| 91在线看 | 免费看的毛片 | 在线观看免费观看在线91 | 丁香狠狠 | 久久在视频 | 国产成人免费av电影 | 视频1区2区 | 91精品综合在线观看 | 欧美色图p | 婷婷成人亚洲综合国产xv88 | 中文字幕在线观看第二页 | 五月婷婷色 | 天天天干夜夜夜操 | 国产视频在线播放 | 国产色啪| 色激情在线 | 日韩在线观 | 日韩成人不卡 | 欧美日韩一级视频 | 久久网站免费 | 九九九九热精品免费视频点播观看 | 91麻豆产精品久久久久久 | 中文字幕亚洲欧美 | 亚洲一区二区高潮无套美女 | 国产又黄又爽又猛视频日本 | 欧美精品亚州精品 | 色鬼综合网 | 欧美99久久| 国产日韩在线播放 | 国产超碰在线观看 | 亚洲午夜电影网 | 日韩免| 午夜精品福利一区二区三区蜜桃 | 亚洲三级国产 | 在线观看韩日电影免费 | 亚洲伦理中文字幕 | 九九有精品 | 国内精品毛片 | 91mv.cool在线观看 | 韩国三级在线一区 | 欧美日韩在线视频一区 | 国产成人一区二区啪在线观看 | 精品视频999 | 久久久久欧美精品999 | 国产精品门事件 | 91av在线电影 | 99精品国产免费久久 | 欧美色精品天天在线观看视频 | 久久成人国产精品免费软件 | 国产精品久久久久久久av大片 | 天堂av在线免费观看 | 日韩国产欧美在线播放 | 国产成人久久精品 | 成人中文字幕+乱码+中文字幕 | 狠狠干婷婷 | 国产韩国日本高清视频 | zzijzzij亚洲日本少妇熟睡 | 国产成人高清 | 欧美精品亚洲二区 | 人人网人人爽 | 网站免费黄 | 亚洲无毛专区 | 91一区啪爱嗯打偷拍欧美 | 午夜精品视频一区 | 黄色软件视频网站 | 亚洲永久av | 免费精品视频在线 | www天天干com | 992tv在线成人免费观看 | 91视频在线自拍 | 在线观看视频你懂得 | 波多野结衣在线视频一区 | 国产精品你懂的在线观看 | 日日操狠狠干 | 黄色片亚洲 | 亚洲精品ww | 成人99免费视频 | 中文字幕超清在线免费 | 97视频播放| 成人国产精品一区二区 | 国内精品久久天天躁人人爽 | 亚洲国产精品日韩 | 欧美日韩高清一区二区三区 | 国产成人高清在线 | 久久久久久片 | 日韩视频一区二区 | 国产传媒中文字幕 | 天天操操操操操 | 伊人看片 | 亚洲成人国产 | 二区三区在线 | 在线国产片| 一本一本久久a久久精品综合妖精 | 日韩免费一级a毛片在线播放一级 | 国产69精品久久久久9999apgf | 国产精品一区二区三区久久久 | 91丨九色丨首页 | 久久情侣偷拍 | 日本三级久久久 | 精品一区二区在线免费观看 | 国产精品99爱 | av电影中文 | 91高清不卡| 国产999在线观看 | 国产精品女人久久久 | 97超级碰碰碰视频在线观看 | 在线观看91精品国产网站 | 久久久午夜精品理论片中文字幕 | 婷婷色视频 | 精品一区电影国产 | 天堂在线v | 成人av高清 | 国产精品9999久久久久仙踪林 | 九九热视频在线免费观看 | 欧美日韩亚洲国产一区 | 久久久久亚洲精品中文字幕 | 亚洲另类交 | 亚洲精品在线观看免费 | 久久久国产精品一区二区中文 | 人人爱爱 | 91麻豆精品国产91久久久久久久久 | 激情小说 五月 | 色婷婷激情电影 | 欧洲精品久久久久毛片完整版 | 伊人色综合久久天天网 | 91爱爱中文字幕 | 中文字幕一区二区在线观看 | 欧美一区二区三区激情视频 | 久久久.com| 一区精品在线 | 久久国产午夜精品理论片最新版本 | 久久综合网色—综合色88 | 97碰在线视频 | 久久久久久久久久久久av | 久久久国产99久久国产一 | 在线黄色av电影 | 精品国产诱惑 | 日韩剧情 | 日本性动态图 | 日日夜色 | 婷婷在线免费视频 | 中日韩欧美精彩视频 | 国产小视频在线免费观看 | 免费在线视频一区二区 | 久热只有精品 | 播五月综合 | 国产精品久久久久久电影 | 日韩理论电影在线 | 日本黄色黄网站 | 99久国产 | 91亚洲影院 | 西西444www大胆无视频 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 国内外成人免费在线视频 | 青青河边草免费视频 | 91福利视频久久久久 | 国产精品久久综合 | 国产一区二区精 | 四虎在线影视 | 日韩精品一区二区三区水蜜桃 | 国产成人在线观看免费 | 久久综合九色综合久99 | 亚洲欧洲成人精品av97 | 九九免费在线观看视频 | 精品国产1区 | 特级西西人体444是什么意思 | 日本激情视频中文字幕 | 色插综合| 国产福利免费在线观看 | 91麻豆精品国产自产在线游戏 | 337p日本欧洲亚洲大胆裸体艺术 | 日韩免费一级a毛片在线播放一级 | 免费一级片视频 | 色噜噜在线观看视频 | 成年人黄色在线观看 | 日韩精品一区二区三区视频播放 | 国产免费一区二区三区最新 | av夜夜操| 亚洲一区二区视频在线播放 | 狠狠色丁香婷婷综合欧美 | 国内精品久久久久久久97牛牛 | 91av在线不卡 | 综合国产视频 | av成人在线观看 | 97超碰中文字幕 | 中文字幕123区 | 波多野结衣在线视频一区 | 一区二区三区在线观看中文字幕 | 欧美高清成人 | 国产美女视频网站 | 国内精品久久久久久久久久清纯 | a在线一区 | 国产精品久久久久久久久久久久午夜片 | 97成人啪啪网 | av一区二区三区在线播放 | 国产香蕉97碰碰久久人人 | 日韩av不卡在线 | 五月综合| 免费麻豆| 国产无吗一区二区三区在线欢 | 成人免费在线播放 | 国产一级片免费播放 | 婷婷丁香在线 | 99热精品久久 | 欧美日韩中文国产 | 美女国内精品自产拍在线播放 | 欧美国产亚洲精品久久久8v | 91精品久久久久久久久久入口 | 免费人做人爱www的视 | 久久久久久久久久久网 | 日韩在线国产精品 | 青青河边草观看完整版高清 | 欧美日韩高清一区二区三区 | 久久天天躁 | 99在线看 | 人人爽久久久噜噜噜电影 | 狠狠色丁香久久婷婷综合五月 | 国产精品女 | 黄色avwww | 国产美女免费看 | 99热国产在线中文 | 久久精品站| 国产精品九九久久久久久久 | 免费av小说 | 一区二区不卡视频在线观看 | 国产视频手机在线 | 中文字幕一区二区三区久久蜜桃 | 久久成人一区二区 | 日韩黄色中文字幕 | 正在播放一区二区 | 欧美整片sss| 在线观看一区二区视频 | 97在线视频免费观看 | av网址在线播放 | 中文字幕亚洲综合久久五月天色无吗'' | 国产精品12345 | 成人小视频在线免费观看 | 91污视频在线观看 | 97精产国品一二三产区在线 | 亚洲涩涩色 | 最近能播放的中文字幕 | 中文国产字幕在线观看 | 亚洲精品777| 亚洲女人av | 国产99在线免费 | 国产品久精国精产拍 | 日韩av电影国产 | 国产小视频在线免费观看视频 | 国产精品久久99精品毛片三a | 久久经典国产 | 国产最新视频在线观看 | 国产字幕在线看 | 精品久久91 | 99久久影视 | 国产午夜精品一区二区三区嫩草 | 免费视频黄色 | 天堂av中文字幕 | 久久精品男人的天堂 | 亚洲最新在线视频 | 久久字幕 | 精品国产一区二区三区久久影院 | 97在线观看免费观看 | 亚洲理论在线观看电影 | 日韩国产精品一区 | 国产精品99久久久久久大便 | 中文字幕你懂的 | 日韩激情精品 | 五月婷婷av在线 | 亚洲欧美日本A∨在线观看 青青河边草观看完整版高清 | 免费一级黄色 | 97色婷婷成人综合在线观看 | 亚洲一区二区视频在线播放 | 人人爽影院 | 日韩欧美区 | 久久综合丁香 | 99亚洲国产| 在线观看一区二区精品 | 国产97色 | 97精品久久人人爽人人爽 | 亚洲精品网址在线观看 | 天天干夜夜爱 | 亚洲国产成人av网 | 色婷婷五| 国产精品女主播一区二区三区 | 国产精品第一页在线 | 日韩中文字幕国产 | 久久久久99精品成人片三人毛片 | 97av超碰| 91麻豆精品国产自产 | 欧美一级免费片 | 五月天丁香亚洲 | 亚洲天堂网在线视频观看 | 婷婷久久综合网 | 国产综合婷婷 | 一区二区 久久 | 免费看搞黄视频网站 | 特级西西人体444是什么意思 | 日韩精品视频久久 | 免费人成在线观看网站 | av直接看 | 超碰99在线 | 欧美大片在线看免费观看 | 成人9ⅰ免费影视网站 | 成人免费在线观看入口 | 久久精品一区二区三区视频 | 日韩有码中文字幕在线 | 国产黄网在线 | 免费久久99精品国产婷婷六月 | 黄毛片在线观看 | 一区二区三区 亚洲 | 亚洲国产中文字幕在线视频综合 | 日韩av免费观看网站 | 四虎影视成人永久免费观看视频 | 美女网站一区 | 国产三级av在线 | 99久久久成人国产精品 | 免费高清无人区完整版 | 人人讲下载 | 涩av在线| 亚洲一区二区精品视频 | 99免费在线观看视频 | 亚洲激情在线播放 | 中文一区在线观看 | 国产日韩视频在线播放 | 在线视频观看你懂的 | 国产又粗又猛又色又黄网站 | 毛片一区二区 | 中文字幕一区二区在线播放 | 亚洲精品久久久久中文字幕m男 | 欧美韩国日本在线观看 | 不卡的av | 国产亚洲精品久久久久5区 成人h电影在线观看 | 99精品国产福利在线观看免费 | 欧美成人亚洲 | 精品视频999| 操夜夜操 | 91视视频在线直接观看在线看网页在线看 | 国产亚洲精品久久久久久久久久 | 国产精品2018 | 91九色国产 | 制服丝袜一区二区 | 91亚洲激情 | 91亚洲精品国偷拍自产在线观看 | 国产一级性生活视频 | 在线观看中文字幕 | 视频在线播放国产 | 久久99精品国产99久久6尤 | 国产日韩精品一区二区 | av成人在线播放 | 久久高清视频免费 | 91黄色小网站 | 成人免费视频免费观看 | 久久99网| 99久久久久成人国产免费 | 国产在线一区二区 | 欧女人精69xxxxxx | 成人一区二区三区在线 | 日日夜夜天天干 | 亚洲国产mv | 国产精品一区免费看8c0m | 911香蕉视频 | 在线观看免费一级片 | 免费看的黄色录像 | 国产精品丝袜 | 81国产精品久久久久久久久久 | 天天干夜夜爱 | 黄色一二级片 | 亚洲 综合 精品 | 探花在线观看 | 粉嫩aⅴ一区二区三区 | 久久黄色片 | 午夜性盈盈 | av电影免费看 | 激情综合六月 | 国产高清视频在线播放 | 免费看污污视频的网站 | 九9热这里真品2 | 国产打女人屁股调教97 | 免费视频久久久久久久 | 99久久网站 | 天天干,天天射,天天操,天天摸 | 亚一亚二国产专区 | 亚洲国产精品影院 | 黄色精品网站 | 国产一级大片在线观看 | 制服丝袜在线 | 国产精品久久一卡二卡 | 亚洲专区在线播放 | 国产女人免费看a级丨片 | 婷婷五月在线视频 | 国产精品毛片一区二区在线 | 亚洲视频在线播放 | 一区二区三区影院 | 久久国内精品99久久6app | 欧美日韩国产二区三区 | 国产精品黄色 | 婷婷亚洲综合五月天小说 | 国产一区精品在线观看 | 日韩精品在线观看视频 | 中文字幕日韩一区二区三区不卡 | 国产在线不卡精品 | 夜色资源站wwwcom | 日本二区三区在线 | 狠狠色狠狠色终合网 | 国产成人亚洲在线观看 | 特黄特黄的视频 | 91福利视频免费观看 | 黄色亚洲精品 | 亚洲精品在 | 久视频在线 | 中文字幕成人 | 中文字幕亚洲精品在线观看 | 国产精品区免费视频 | 深爱激情开心 | 激情喷水 | 午夜视频免费在线观看 | 欧美一级电影片 | 天天综合在线观看 | 在线午夜电影神马影院 | 久久久久久久久久免费视频 | 九九九九九国产 | 91av美女| 久久久久久久久久久久国产精品 | 91天天视频| 国产女人40精品一区毛片视频 | 久草在线综合 | 国产午夜三级一区二区三桃花影视 | 欧美性极品xxxx娇小 | 91免费观看视频网站 | 五月综合久久 | 免费观看的av | 久久国产精彩视频 | 久久久国产精品一区二区三区 | 综合久久网站 | 伊人国产在线播放 | 91在线入口| 成人91在线观看 | 日韩免费b | 九精品 | 91污污视频在线观看 | 91av社区 | 亚洲一区日韩精品 | 国产色视频 | 久久九九国产视频 | 免费看片网页 | 亚洲欧美婷婷六月色综合 | 久久精品在线免费观看 |