您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 咨询培训 > Android应用程序消息处理机制分析
Android应用程序消息处理机制分析Android像Windows、MiniGui等大多数系统一样都是通过消息来驱动的,特殊的是Android为每一个应用程序维护一个消息队列和消息循环,应用程序的主线程不断地从这个消息队列中获取消息,然后对这些消息进行处理,这样就实现了通过消息来驱动执行应用程序。Android应用程序都是由Activity组成的,在我们点击主界面的应用程序图标后,Launch程序一般情况下会通知ActivityManagerService向zygote发出请求,为应用程序创建一个新的进程并启动一个默认的Activity。而应用程序的进程入口是ActivityThread.main,我们可以理解为应用程序框架层为应用程序创建进程后,就把ActivityThread类加载进来,然后执行它的main函数。本文就以ActivityManagerService通知应用程序加载MainActivity为例,分析Android应用程序的消息处理机制(Looper、Handler)。这个过程,Launch通过ActivityManagerService给ActivityThread发送请求,请求启动MainActivity,这里ActivityManagerService只是把请求封装成一个消息,然后通过quequeOrSendMessage把消息放到应用程序的消息队列中,并没有等待请求操作完成就返回了。应用程序发现消息队列有消息时,通过handleMessage处理这个消息,即调用handleLaunchActivity来执行实际的加载MainAcitivy类的操作。了解Android应用程序的消息处理过程后,就开始分析它的实现原理吧。与Windows应用程序的消息处理过程一样,Android应用程序的消息处理机制也是由消息循环、消息发送和消息处理这三个部分组成的。重要的概念(类)首先大概了解几个重要的概念(类):Message:消息,可以理解为线程间通信的数据单元。MessageQueue:消息队列,用来存储一些待分发的Message,内部实现了一个Message链表结构,一般按照先进先出原则执行(当然也有优先级或是时间排序等)。Handler:是Message的主要处理者,负责将message添加到消息队列中以及对消息队列的Message进行处理(即分发消息)。Looper:循环器,帮助一个线程维护一个消息队列,循环取出MessageQueueLaunch通过ActivityManagerService发送请求msg放到应用程序的消息队列handleMessage处理消息中的Message,并交给相应的Handler处理。线程:UIthread通常就是mainthread,而Android启动程序时会替它建立一个MessageQueue。每一个线程里可以含有一个Looper对象以及一个MessageQueue数据结构。在应用程序里,可以定义Handler的子类来接收Looper所发送的消息。下面我们开始分析应用程序消息处理机制的三个过程:1.消息循环在消息处理机制中,消息都是存放在一个消息队列中的,而应用程序主线程就会围绕着这个消息队列进入一个无线循环(Looper),直到程序退出。如果队列中有消息,应用程序主线程就会把它取出来,并分发给相应的Handler处理;如果队列中没有消息,应用程序主线程就会进入空闲等待状态,等待着下一个消息的到来。1.1Looper的创建(Java层)我们先来看一下Android应用程序主线程是怎样进入消息循环的,前面讨论过在应用程序启动时,会在进程中加载ActivityThread类,并执行这个类的main函数,而应用程序的消息循环就是在这个main中实现的,它定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:1.publicfinalclassActivityThread{2.......3.finalHmH=newH();4.......5.publicstaticvoidmain(String[]args){6.......7.Looper.prepareMainLooper();8.......9.ActivityThreadthread=newActivityThread();10.thread.attach(false);11.......12.Looper.loop();13.......14.}15.}这个函数做了两件事情,一是在主线程中创建了一个ActivityThread实例,在创建这个实例时,同时也会创建其成员变量,如mH,它是H类型的,继承于handler;二是通过Looper类使主线程进入消息循环中,这里我们只关注后者。首先看Looper.prepareMainLooper函数的实现,这是一个静态成员函数,定义在Frameworks/base/core/java/android/os/Looper.java文件中:1.publicclassLooper{2.......3.staticfinalThreadLocalLoopersThreadLocal=newThreadLocalLooper();4.finalMessageQueuemQueue;5.......6.publicstaticfinalvoidprepare(){7.if(sThreadLocal.get()!=null){8.thrownewRuntimeException(OnlyoneLoopermaybecreatedperthread);9.}10.sThreadLocal.set(newLooper());11.}12.publicstaticfinalvoidprepareMainLooper(){13.prepare();14.setMainLooper(myLooper());15.myLooper().mQueue.mQuitAllowed=false;16.}17.privatesynchronizedstaticvoidsetMainLooper(Looperlooper){18.mMainLooper=looper;19.}20.publicstaticfinalLoopermyLooper(){21.return(Looper)sThreadLocal.get();22.}23.privateLooper(){24.mQueue=newMessageQueue();25.mRun=true;26.mThread=Thread.currentThread();27.}28.......29.}其实prepareMainLooper所做的事情就是在线程中创建一个Looper对象,这个Looper对象存放在sThreadLocal成员变量中,sThreadLocal的类型是ThreadLocal,表示这是一个线程局部变量,而它又是static、final型的,即保证每一个调用了prepare函数的线程里都有一个独立的Looper对象。在创建Looper对象时,在其构造函数中可以知道,它创建了一个消息队列MessageQueue,并保存在mQueue成员变量中,而往后的消息就是存放在这个队列中的。消息队列是消息处理机制的重要组件,所以我们看下它的创建过程,即构造函数的实现,实现frameworks/base/core/java/android/os/MessageQueue.java中:1.publicclassMessageQueue{2.......3.privateintmPtr;//usedbynativecode4.privatenativevoidnativeInit();5.6.MessageQueue(){7.nativeInit();8.}9.......10.}MessageQueue的初始化工作都交给了JNI方法nativeInit来实现了,这个JNI方法定义在Frameworks/base/core/jni/android_os_MessageQueue.cpp中:1.staticvoidandroid_os_MessageQueue_nativeInit(JNIEnv*env,jobjectobj){2.NativeMessageQueue*nativeMessageQueue=newNativeMessageQueue();3.......4.android_os_MessageQueue_setNativeMessageQueue(env,obj,nativeMessageQueue);5.}6.NativeMessageQueue::NativeMessageQueue(){7.mLooper=Looper::getForThread();8.if(mLooper==NULL){9.mLooper=newLooper(false);10.Looper::setForThread(mLooper);11.}12.}13.staticvoidandroid_os_MessageQueue_setNativeMessageQueue(JNIEnv*env,jobjectmessageQueueObj,14.NativeMessageQueue*nativeMessageQueue){15.env-SetIntField(messageQueueObj,gMessageQueueClassInfo.mPtr,16.reinterpret_castjint(nativeMessageQueue));17.}18.......19.#defineFIND_CLASS(var,className)\20.var=env-FindClass(className);\21.LOG_FATAL_IF(!var,UnabletofindclassclassName);22.#defineGET_FIELD_ID(var,clazz,fieldName,fieldDescriptor)\23.var=env-GetFieldID(clazz,fieldName,fieldDescriptor);\24.LOG_FATAL_IF(!var,UnabletofindfieldfieldName);25.intregister_android_os_MessageQueue(JNIEnv*env){26.......27.jclassclazz;28.FIND_CLASS(clazz,android/os/MessageQueue);29.GET_FIELD_ID(gMessageQueueClassInfo.mPtr,clazz,30.mPtr,I);31.return0;32.}在andoroid_os_MessageQueue_nativeInit函数里,JNI层也相应地创建了一个消息队列NativeMessageQueue,NativeMessageQueue类主要在内部创建了一个Looper对象,而这个Looper对象是实现在C++层的,它与之前说过的Java层的Looper是不一样的,不过它们是对应的,在进一步分析消息循环过程时,我们就可以清楚地了解它们之间的关系了。先来分析android_os_MessageQueue_setNativeMessageQueue函数吧,在创建了本地消息队列NativeMessageQueue后,通过调用android_os_MessageQueue_setNativeMessageQueue把本地消息队列保存在Java层的MessageQueue对象中的mPtr成员变量里。函数所传的参数MessageQueueObj是Java层创建的消息队列,env可以理解成:通过它我们可以很方便地进行JNI层与Java层间的交互
本文标题:Android应用程序消息处理机制分析
链接地址:https://www.777doc.com/doc-3351274 .html