Android是消息驱动的,实现消息驱动有几个要素:
(1)消息的默示:Message
(2 )消息队列:MessageQueue
(3 )消息轮回,用于轮回取出消息进行处理惩罚:Looper
(4 )消息处理惩罚,消息轮回从消息队列中取出消息后要对消息进行处理惩罚:Handler
日常平凡我们最常应用的就是Message与Handler了,若是应用过HandlerThread或者本身实现类似HandlerThread的器材可能还会接触到Looper,而MessageQueue是Looper内部应用的,对于标准的SDK,我们是无法实例化并应用的(机关函数是包可见性)。
我们日常平凡接触到的Looper、Message、Handler都是用JAVA实现的,Android做为基于Linux的体系,底层用C、C++实现的,并且还有NDK的存在,消息驱动的模型怎么可能只存在于JAVA层,实际上,在Native层存在与Java层对应的类如Looper、MessageQueue等。
初始化消息队列
起首来看一下若是一个线程想实现消息轮回应当怎么做,以HandlerThread为例:
publicvoidrun() {
mTid=Process.myTid();
Looper.prepare();
synchronized(this) {
mLooper=Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid= -1;
}
主如果红色标明的两句,起首调用prepare初始化MessageQueue与Looper,然后调用loop进入消息轮回。先看一下Looper.prepare。
publicstaticvoidprepare() {
prepare(true);
}
privatestaticvoidprepare(booleanquitAllowed) {
if(sThreadLocal.get() !=null) {
thrownewRuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(newLooper(quitAllowed));
}
重载函数,quitAllowed默认为true,从名字可以看出来就是消息轮回是否可以退出,默认是可退出的,Main线程(UI线程)初始化消息轮回时会调用prepareMainLooper,传进去的是false。应用了ThreadLocal,每个线程可以初始化一个Looper。
再来看一下Looper在初始化时都做了什么:
privateLooper(booleanquitAllowed) {
mQueue=newMessageQueue(quitAllowed);
mRun=true;
mThread=Thread.currentThread();
}
MessageQueue(booleanquitAllowed) {
mQuitAllowed=quitAllowed;
nativeInit();
}
在Looper初始化时,新建了一个MessageQueue的对象保存了在成员mQueue中。MessageQueue的机关函数是包可见性,所以我们是无法直接应用的,在MessageQueue初始化的时辰调用了nativeInit,这是一个Native办法:
staticvoidandroid_os_MessageQueue_nativeInit(JNIEnv*env, jobject obj) {
NativeMessageQueue* nativeMessageQueue =newNativeMessageQueue();
if(!nativeMessageQueue) {
jniThrowRuntimeException(env,"Unable to allocate native queue");
return;
}
nativeMessageQueue->incStrong(env);
android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
}
staticvoidandroid_os_MessageQueue_setNativeMessageQueue(JNIEnv*env, jobject messageQueueObj,
NativeMessageQueue*nativeMessageQueue) {
env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr,
reinterpret_cast<jint>(nativeMessageQueue));
}
在nativeInit中,new了一个Native层的MessageQueue的对象,并将其地址保存在了Java层MessageQueue的成员mPtr中,Android中有很多多少如许的实现,一个类在Java层与Native层都有实现,经由过程JNI的GetFieldID与SetIntField把Native层的类的实例地址保存到Java层类的实例的mPtr成员中,比如Parcel。
再看NativeMessageQueue的实现:
NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
mLooper=Looper::getForThread();
if(mLooper ==NULL) {
mLooper=newLooper(false);
Looper::setForThread(mLooper);
}
}
在NativeMessageQueue的机关函数中获得了一个Native层的Looper对象,Native层的Looper也应用了线程本地存储,重视new Looper时传入了参数false。
Looper::Looper(boolallowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
intwakeFds[2];
int result =pipe(wakeFds);
LOG_ALWAYS_FATAL_IF(result!=0,"Could not create wake pipe. errno=%d", errno);
mWakeReadPipeFd= wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
result=fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result!=0,"Could not make wake read pipe non-blocking. errno=%d",
errno);
result=fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result!=0,"Could not make wake write pipe non-blocking. errno=%d",
errno);
//Allocate the epoll instance and register the wake pipe.
mEpollFd =epoll_create(EPOLL_SIZE_HINT);
LOG_ALWAYS_FATAL_IF(mEpollFd<0,"Could not create epoll instance. errno=%d", errno);
structepoll_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);
LOG_ALWAYS_FATAL_IF(result!=0,"Could not add wake read pipe to epoll instance. errno=%d",
errno);
}
Native层的Looper应用了epoll。初始化了一个管道,用mWakeWritePipeFd与mWakeReadPipeFd分别保存了管道的写端与读端,并了读端的EPOLLIN事务。重视下初始化列表的值,mAllowNonCallbacks的值为false。
mAllowNonCallback是做什么的?应用epoll仅为了mWakeReadPipeFd的事务?其实Native Looper不仅可以这一个描述符,Looper还供给了addFd办法:
intaddFd(intfd,intident,intevents, ALooper_callbackFunc callback,void*data);
intaddFd(intfd,intident,intevents,constsp<LooperCallback>& callback,void* data);
fd默示要的描述符。ident默示要的事务的标识,值必须>=0或者为ALOOPER_POLL_BACK(-2),event默示要的事务,callback是事务产生时的回调函数,mAllowNonCallbacks的感化就在于此,当mAllowNonCallbacks为true时容许callback为NULL,在pollOnce中ident作为成果返回,不然不容许callback为空,当callback不为NULL时,ident的值会被忽视。还是直接看代码便利懂得:
intLooper::addFd(intfd,intident,intevents,constsp<LooperCallback>& callback,void*data) {
#ifDEBUG_CALLBACKS
ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0 x%x, callback=%p, data=%p",this, fd, ident,
events, callback.get(), data);
#endif
if(!callback.get()) {
if(!mAllowNonCallbacks) {
ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
return-1;
}
if(ident <0) {
ALOGE("Invalid attempt to set NULL callback with ident < 0.");
return-1;
}
}else{
ident=ALOOPER_POLL_CALLBACK;
}
intepollEvents =0;
if(events & ALOOPER_EVENT_INPUT) epollEvents |=EPOLLIN;
if(events & ALOOPER_EVENT_OUTPUT) epollEvents |=EPOLLOUT;
{//acquire lock
AutoMutex _l(mLock);
Request request;
request.fd=fd;
request.ident=ident;
request.callback=callback;
request.data=data;
structepoll_event eventItem;
memset(& eventItem,0,sizeof(epoll_event));//zero out unused members of data field union
eventItem.events =epollEvents;
eventItem.data.fd=fd;
ssize_t requestIndex=mRequests.indexOfKey(fd);
if(requestIndex <0) {
intepollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem);
if(epollResult <0) {
ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
return-1;
}
mRequests.add(fd, request);
}else{
(1)消息的默示:Message
(2 )消息队列:MessageQueue
(3 )消息轮回,用于轮回取出消息进行处理惩罚:Looper
(4 )消息处理惩罚,消息轮回从消息队列中取出消息后要对消息进行处理惩罚:Handler
日常平凡我们最常应用的就是Message与Handler了,若是应用过HandlerThread或者本身实现类似HandlerThread的器材可能还会接触到Looper,而MessageQueue是Looper内部应用的,对于标准的SDK,我们是无法实例化并应用的(机关函数是包可见性)。
我们日常平凡接触到的Looper、Message、Handler都是用JAVA实现的,Android做为基于Linux的体系,底层用C、C++实现的,并且还有NDK的存在,消息驱动的模型怎么可能只存在于JAVA层,实际上,在Native层存在与Java层对应的类如Looper、MessageQueue等。
初始化消息队列
起首来看一下若是一个线程想实现消息轮回应当怎么做,以HandlerThread为例:
publicvoidrun() {
mTid=Process.myTid();
Looper.prepare();
synchronized(this) {
mLooper=Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid= -1;
}
主如果红色标明的两句,起首调用prepare初始化MessageQueue与Looper,然后调用loop进入消息轮回。先看一下Looper.prepare。
publicstaticvoidprepare() {
prepare(true);
}
privatestaticvoidprepare(booleanquitAllowed) {
if(sThreadLocal.get() !=null) {
thrownewRuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(newLooper(quitAllowed));
}
重载函数,quitAllowed默认为true,从名字可以看出来就是消息轮回是否可以退出,默认是可退出的,Main线程(UI线程)初始化消息轮回时会调用prepareMainLooper,传进去的是false。应用了ThreadLocal,每个线程可以初始化一个Looper。
再来看一下Looper在初始化时都做了什么:
privateLooper(booleanquitAllowed) {
mQueue=newMessageQueue(quitAllowed);
mRun=true;
mThread=Thread.currentThread();
}
MessageQueue(booleanquitAllowed) {
mQuitAllowed=quitAllowed;
nativeInit();
}
在Looper初始化时,新建了一个MessageQueue的对象保存了在成员mQueue中。MessageQueue的机关函数是包可见性,所以我们是无法直接应用的,在MessageQueue初始化的时辰调用了nativeInit,这是一个Native办法:
staticvoidandroid_os_MessageQueue_nativeInit(JNIEnv*env, jobject obj) {
NativeMessageQueue* nativeMessageQueue =newNativeMessageQueue();
if(!nativeMessageQueue) {
jniThrowRuntimeException(env,"Unable to allocate native queue");
return;
}
nativeMessageQueue->incStrong(env);
android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
}
staticvoidandroid_os_MessageQueue_setNativeMessageQueue(JNIEnv*env, jobject messageQueueObj,
NativeMessageQueue*nativeMessageQueue) {
env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr,
reinterpret_cast<jint>(nativeMessageQueue));
}
在nativeInit中,new了一个Native层的MessageQueue的对象,并将其地址保存在了Java层MessageQueue的成员mPtr中,Android中有很多多少如许的实现,一个类在Java层与Native层都有实现,经由过程JNI的GetFieldID与SetIntField把Native层的类的实例地址保存到Java层类的实例的mPtr成员中,比如Parcel。
再看NativeMessageQueue的实现:
NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
mLooper=Looper::getForThread();
if(mLooper ==NULL) {
mLooper=newLooper(false);
Looper::setForThread(mLooper);
}
}
在NativeMessageQueue的机关函数中获得了一个Native层的Looper对象,Native层的Looper也应用了线程本地存储,重视new Looper时传入了参数false。
Looper::Looper(boolallowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
intwakeFds[2];
int result =pipe(wakeFds);
LOG_ALWAYS_FATAL_IF(result!=0,"Could not create wake pipe. errno=%d", errno);
mWakeReadPipeFd= wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
result=fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result!=0,"Could not make wake read pipe non-blocking. errno=%d",
errno);
result=fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result!=0,"Could not make wake write pipe non-blocking. errno=%d",
errno);
//Allocate the epoll instance and register the wake pipe.
mEpollFd =epoll_create(EPOLL_SIZE_HINT);
LOG_ALWAYS_FATAL_IF(mEpollFd<0,"Could not create epoll instance. errno=%d", errno);
structepoll_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);
LOG_ALWAYS_FATAL_IF(result!=0,"Could not add wake read pipe to epoll instance. errno=%d",
errno);
}
Native层的Looper应用了epoll。初始化了一个管道,用mWakeWritePipeFd与mWakeReadPipeFd分别保存了管道的写端与读端,并了读端的EPOLLIN事务。重视下初始化列表的值,mAllowNonCallbacks的值为false。
mAllowNonCallback是做什么的?应用epoll仅为了mWakeReadPipeFd的事务?其实Native Looper不仅可以这一个描述符,Looper还供给了addFd办法:
intaddFd(intfd,intident,intevents, ALooper_callbackFunc callback,void*data);
intaddFd(intfd,intident,intevents,constsp<LooperCallback>& callback,void* data);
fd默示要的描述符。ident默示要的事务的标识,值必须>=0或者为ALOOPER_POLL_BACK(-2),event默示要的事务,callback是事务产生时的回调函数,mAllowNonCallbacks的感化就在于此,当mAllowNonCallbacks为true时容许callback为NULL,在pollOnce中ident作为成果返回,不然不容许callback为空,当callback不为NULL时,ident的值会被忽视。还是直接看代码便利懂得:
intLooper::addFd(intfd,intident,intevents,constsp<LooperCallback>& callback,void*data) {
#ifDEBUG_CALLBACKS
ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0 x%x, callback=%p, data=%p",this, fd, ident,
events, callback.get(), data);
#endif
if(!callback.get()) {
if(!mAllowNonCallbacks) {
ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
return-1;
}
if(ident <0) {
ALOGE("Invalid attempt to set NULL callback with ident < 0.");
return-1;
}
}else{
ident=ALOOPER_POLL_CALLBACK;
}
intepollEvents =0;
if(events & ALOOPER_EVENT_INPUT) epollEvents |=EPOLLIN;
if(events & ALOOPER_EVENT_OUTPUT) epollEvents |=EPOLLOUT;
{//acquire lock
AutoMutex _l(mLock);
Request request;
request.fd=fd;
request.ident=ident;
request.callback=callback;
request.data=data;
structepoll_event eventItem;
memset(& eventItem,0,sizeof(epoll_event));//zero out unused members of data field union
eventItem.events =epollEvents;
eventItem.data.fd=fd;
ssize_t requestIndex=mRequests.indexOfKey(fd);
if(requestIndex <0) {
intepollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem);
if(epollResult <0) {
ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
return-1;
}
mRequests.add(fd, request);
}else{