您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 咨询培训 > Android应用程序消息处理机制(LooperHandler)分析
Android应用程序消息处理机制(Looper、Handler)分析Android应用程序是通过消息来驱动的,系统为每一个应用程序维护一个消息队例,应用程序的主线程不断地从这个消息队例中获取消息(Looper),然后对这些消息进行处理(Handler),这样就实现了通过消息来驱动应用程序的执行,本文将详细分析Android应用程序的消息处理机制。前面我们学习Android应用程序中的Activity启动(和)、Service启动(和)以及广播发送()时,它们都有一个共同的特点,当ActivityManagerService需要与应用程序进行并互时,如加载Activity和Service、处理广播待,会通过来知会应用程序,应用程序接收到这个请求时,它不是马上就处理这个请求,而是将这个请求封装成一个消息,然后把这个消息放在应用程序的消息队列中去,然后再通过消息循环来处理这个消息。这样做的好处就是消息的发送方只要把消息发送到应用程序的消息队列中去就行了,它可以马上返回去处理别的事情,而不需要等待消息的接收方去处理完这个消息才返回,这样就可以提高系统的并发性。实质上,这就是一种异步处理机制。这样说可能还是比较笼统,我们以一文中所介绍的应用程序启动过程的一个片断来具体看看是如何这种消息处理机制的。在这篇文章中,要启动的应用程序称为Activity,它的默认Activity是MainActivity,它是由Launcher来负责启动的,而Launcher又是通过ActivityManagerService来启动的,当ActivityManagerService为这个即将要启的应用程序准备好新的进程后,便通过一个来通知这个新的进程来加载MainActivity,如下图所示:它对应Android应用程序启动过程中的Step30到Step35,有兴趣的读者可以回过头去参考一文。这里的Step30中的scheduleLaunchActivity是ActivityManagerService通过发送过来的请求,它请求应用程序中的ActivityThread执行Step34中的performLaunchActivity操作,即启动MainActivity的操作。这里我们就可以看到,Step30的这个请求并没有等待Step34这个操作完成就返回了,它只是把这个请求封装成一个消息,然后通过Step31中的queueOrSendMessage操作把这个消息放到应用程序的消息队列中,然后就返回了。应用程序发现消息队列中有消息时,就会通过Step32中的handleMessage操作来处理这个消息,即调用Step33中的handleLaunchActivity来执行实际的加载MainAcitivy类的操作。了解Android应用程序的消息处理过程之后,我们就开始分样它的实现原理了。与Windows应用程序的消息处理过程一样,Android应用程序的消息处理机制也是由消息循环、消息发送和消息处理这三个部分组成的,接下来,我们就详细描述这三个过程。1.消息循环在消息处理机制中,消息都是存放在一个消息队列中去,而应用程序的主线程就是围绕这个消息队列进入一个无限循环的,直到应用程序退出。如果队列中有消息,应用程序的主线程就会把它取出来,并分发给相应的Handler进行处理;如果队列中没有消息,应用程序的主线程就会进入空闲等待状态,等待下一个消息的到来。在Android应用程序中,这个消息循环过程是由Looper类来实现的,它定义在frameworks/base/core/Java/android/os/Looper.java文件中,在分析这个类之前,我们先看一下Android应用程序主线程是如何进入到这个消息循环中去的。在一文中,我们分析了Android应用程序进程的启动过程,Android应用程序进程在启动的时候,会在进程中加载ActivityThread类,并且执行这个类的main函数,应用程序的消息循环过程就是在这个main函数里面实现的,我们来看看这个函数的实现,它定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:[java]viewplaincopy在CODE上查看代码片派生到我的代码片publicfinalclassActivityThread{......publicstaticfinalvoidmain(String[]args){......Looper.prepareMainLooper();......ActivityThreadthread=newActivityThread();thread.attach(false);......Looper.loop();......thread.detach();......}}这个函数做了两件事情,一是在主线程中创建了一个ActivityThread实例,二是通过Looper类使主线程进入消息循环中,这里我们只关注后者。首先看Looper.prepareMainLooper函数的实现,这是一个静态成员函数,定义在frameworks/base/core/java/android/os/Looper.java文件中:[java]viewplaincopy在CODE上查看代码片派生到我的代码片publicclassLooper{......privatestaticfinalThreadLocalsThreadLocal=newThreadLocal();finalMessageQueuemQueue;....../**Initializethecurrentthreadasalooper.*Thisgivesyouachancetocreatehandlersthatthenreference*thislooper,beforeactuallystartingtheloop.Besuretocall*{@link#loop()}aftercallingthismethod,andenditbycalling*{@link#quit()}.*/publicstaticfinalvoidprepare(){if(sThreadLocal.get()!=null){thrownewRuntimeException(OnlyoneLoopermaybecreatedperthread);}sThreadLocal.set(newLooper());}/**Initializethecurrentthreadasalooper,markingitasanapplication'smain*looper.ThemainlooperforyourapplicationiscreatedbytheAndroidenvironment,*soyoushouldneverneedtocallthisfunctionyourself.*{@link#prepare()}*/publicstaticfinalvoidprepareMainLooper(){prepare();setMainLooper(myLooper());if(Process.supportsProcesses()){myLooper().mQueue.mQuitAllowed=false;}}privatesynchronizedstaticvoidsetMainLooper(Looperlooper){mMainLooper=looper;}/***ReturntheLooperobjectassociatedwiththecurrentthread.Returns*nullifthecallingthreadisnotassociatedwithaLooper.*/publicstaticfinalLoopermyLooper(){return(Looper)sThreadLocal.get();}privateLooper(){mQueue=newMessageQueue();mRun=true;mThread=Thread.currentThread();}......}函数prepareMainLooper做的事情其实就是在线程中创建一个Looper对象,这个Looper对象是存放在sThreadLocal成员变量里面的,成员变量sThreadLocal的类型为ThreadLocal,表示这是一个线程局部变量,即保证每一个调用了prepareMainLooper函数的线程里面都有一个独立的Looper对象。在线程是创建Looper对象的工作是由prepare函数来完成的,而在创建Looper对象的时候,会同时创建一个消息队列MessageQueue,保存在Looper的成员变量mQueue中,后续消息就是存放在这个队列中去。消息队列在Android应用程序消息处理机制中最重要的组件,因此,我们看看它的创建过程,即它的构造函数的实现,实现frameworks/base/core/java/android/os/MessageQueue.java文件中:[java]viewplaincopy在CODE上查看代码片派生到我的代码片publicclassMessageQueue{......privateintmPtr;//usedbynativecodeprivatenativevoidnativeInit();MessageQueue(){nativeInit();}......}它的初始化工作都交给JNI方法nativeInit来实现了,这个JNI方法定义在frameworks/base/core/jni/android_os_MessageQueue.cpp文件中:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片staticvoidandroid_os_MessageQueue_nativeInit(JNIEnv*env,jobjectobj){NativeMessageQueue*nativeMessageQueue=newNativeMessageQueue();if(!nativeMessageQueue){jniThrowRuntimeException(env,Unabletoallocatenativequeue);return;}android_os_MessageQueue_setNativeMessageQueue(env,obj,nativeMessageQueue);}在JNI中,也相应地创建了一个消息队列NativeMessageQueue,NativeMessageQueue类也是定义在frameworks/base/core/jni/android_os_MessageQueue.cpp文件中,它的创建过程如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片NativeMessageQueue::NativeMessageQueue(){mLooper=Looper::getForThread();if(mLooper==NULL){mLooper=newLooper(false);Looper::setForThread(mLooper);}}它主要就是在内部创建了一个Looper对象,注意,这个Looper对象是实现在JNI层的,它与上面Java层中的Looper是不一样的,不过它们是对应的,下面我们进一步分析消息循环的过程的时候,读者就会清楚地了解到它们之间的关系。这个Looper的创建过程也很重要,不过我们暂时放一放,先分析完android_os_MessageQueue_nativeInit函数的执行,它创建了本地消息队列NativeMessageQueue对象之后,接着调用android_os_MessageQueue_setNativeMessage
本文标题:Android应用程序消息处理机制(LooperHandler)分析
链接地址:https://www.777doc.com/doc-2897277 .html