概述
这里介绍下Android中利用ALooper进行消息传递和处理的用法及工作原理。
利用ALooper进行消息传递即处理涉及到的类关系图如下:
AMessage类:消息类,用于构造消息,并通过post方法投递出去由ALooperRoster 类中转给ALooper
ALooperRoster类:中转类,将消息中转给ALooper 或者 AHandleReflector
ALooper:与AHandle一一对应,负责存储和转发AHandle的消息
LooperThread:此线程循环调用ALooper的loop方法来转发消息
AHandleReflector类:消息处理类
下面依据图并结合具体代码介绍下消息传递及处理流程
流程代码分析
图中的箭头部分代表了调用顺序:
1 注册handle: 语句mLooper->registerHandler(mHandler); 这样就建立了ALooper与AHandle的一一对应关系,要发送给AHandle处理的消息,都会经过ALooper存储和转发
mLooper(new ALooper),
mHandler(new AHandlerReflector<SimpleSoftOMXComponent>(this)), mLooper->setName(name); mLooper->registerHandler(mHandler); mLooper->start( false, // runOnCallingThread false, // canCallJava ANDROID_PRIORITY_FOREGROUND);
看下registerHandler实现
ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) { return gLooperRoster.registerHandler(this, handler); }
主要是将ALooper和AHandle注册到ALooperRoster中,继续跟进
ALooper::handler_id ALooperRoster::registerHandler( const sp<ALooper> looper, const sp<AHandler> &handler) { Mutex::Autolock autoLock(mLock); if (handler->id() != 0) { CHECK(!"A handler must only be registered once."); return INVALID_OPERATION; } HandlerInfo info; info.mLooper = looper; info.mHandler = handler; ALooper::handler_id handlerID = mNextHandlerID++; mHandlers.add(handlerID, info); handler->setID(handlerID); return handlerID; }
将ALooper与AHandle 信息存储在mHandles 列表中, 可以存储多个<ALooper,AHandle >
注册完成后调用start启动ALooper开始工作
status_t ALooper::start( bool runOnCallingThread, bool canCallJava, int32_t priority) { if (runOnCallingThread) { { Mutex::Autolock autoLock(mLock); if (mThread != NULL || mRunningLocally) { return INVALID_OPERATION; } mRunningLocally = true; } do { } while (loop()); return OK; } Mutex::Autolock autoLock(mLock); if (mThread != NULL || mRunningLocally) { return INVALID_OPERATION; } mThread = new LooperThread(this, canCallJava); status_t err = mThread->run( mName.empty() ? "ALooper" : mName.c_str(), priority); if (err != OK) { mThread.clear(); } return err; }
这里主要是构造了一个LooperThread线程,此线程会循环调用其threadLoop
virtual bool threadLoop() { return mLooper->loop(); }
来处理消息,loop代码后面来看
这里看下threadLoop 在基类Thread中的介绍
// Derived class must implement threadLoop(). The thread starts its life
// here. There are two ways of using the Thread object:
// 1) loop: if threadLoop() returns true, it will be called again if
// requestExit() wasn't called.
// 2) once: if threadLoop() returns false, the thread will exit upon return.
virtual bool threadLoop() = 0;
这里的意思是 当threadLoop返回true时,会循环调用此方法,否则就终止线程
因此当threadLoop一直返回true,则可以看成是一个循环。
2 发送消息:通过构造AMessage对象,初始化参数后调用post方法发送
sp<AMessage> msg = new AMessage(kWhatSendCommand, mHandler->id()); msg->setInt32("cmd", cmd); msg->setInt32("param", param); msg->post();
void AMessage::post(int64_t delayUs) { gLooperRoster.postMessage(this, delayUs); }
3 中转:消息通过ALooperRoster来转发给ALooper
status_t ALooperRoster::postMessage( const sp<AMessage> &msg, int64_t delayUs) { Mutex::Autolock autoLock(mLock); return postMessage_l(msg, delayUs); }
status_t ALooperRoster::postMessage_l( const sp<AMessage> &msg, int64_t delayUs) { ssize_t index = mHandlers.indexOfKey(msg->target()); if (index < 0) { ALOGW("failed to post message. Target handler not registered."); return -ENOENT; } const HandlerInfo &info = mHandlers.valueAt(index); sp<ALooper> looper = info.mLooper.promote(); if (looper == NULL) { ALOGW("failed to post message. " "Target handler %d still registered, but object gone.", msg->target()); mHandlers.removeItemsAt(index); return -ENOENT; } looper->post(msg, delayUs); return OK; }
4 ALooper存储消息
void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) { Mutex::Autolock autoLock(mLock); int64_t whenUs; if (delayUs > 0) { whenUs = GetNowUs() + delayUs; } else { whenUs = GetNowUs(); } List<Event>::iterator it = mEventQueue.begin(); while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) { ++it; } Event event; event.mWhenUs = whenUs; event.mMessage = msg; if (it == mEventQueue.begin()) { mQueueChangedCondition.signal(); } mEventQueue.insert(it, event); }
从代码里可以看到,消息存储在了mEventQueue中,mEventQueue 是封装了AMessage的结构体
5 ALooperRoster 中转
前面说了,LooperThread会调用threadLoop方法
virtual bool threadLoop() { return mLooper->loop(); }
实际调用的是ALooper的loop方法,而且如果loop返回true,则会循环调用
bool ALooper::loop() { Event event; { Mutex::Autolock autoLock(mLock); if (mThread == NULL && !mRunningLocally) { return false; } if (mEventQueue.empty()) { mQueueChangedCondition.wait(mLock); return true; } int64_t whenUs = (*mEventQueue.begin()).mWhenUs; int64_t nowUs = GetNowUs(); if (whenUs > nowUs) { int64_t delayUs = whenUs - nowUs; mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll); return true; } event = *mEventQueue.begin(); mEventQueue.erase(mEventQueue.begin()); } gLooperRoster.deliverMessage(event.mMessage); // NOTE: It's important to note that at this point our "ALooper" object // may no longer exist (its final reference may have gone away while // delivering the message). We have made sure, however, that loop() // won't be called again. return true; }
代码主要是做如下工作:查看mEventQueue是否有message,如果有,且时间正确,则调用gLooperRoster.deliverMessage中转出去
而ALooperRoster实际代码为
void ALooperRoster::deliverMessage(const sp<AMessage> &msg) { sp<AHandler> handler; { Mutex::Autolock autoLock(mLock); ssize_t index = mHandlers.indexOfKey(msg->target()); if (index < 0) { ALOGW("failed to deliver message. Target handler not registered."); return; } const HandlerInfo &info = mHandlers.valueAt(index); handler = info.mHandler.promote(); if (handler == NULL) { ALOGW("failed to deliver message. " "Target handler %d registered, but object gone.", msg->target()); mHandlers.removeItemsAt(index); return; } } handler->onMessageReceived(msg); }
主要就是调用AHandle的onMessageReceived进行处理
6 AHandle处理函数执行
这样一个消息从给投递到处理流程就结束了。 理清调用关系:主要是到ALooper中暂存,并借由全局变量gLooperRoster中转,完成了消息的传递。
【结束】