您的位置:首页 > 运维架构

安卓异步消息处理机制源码流程

2017-03-03 13:44 537 查看

1.源码流程贴图

1.1源码例子部分代码贴图

NuPlayerDriver::NuPlayerDriver(pid_t pid)
: mState(STATE_IDLE),
mIsAsyncPrepare(false),
mAsyncResult(UNKNOWN_ERROR),
mSetSurfaceInProgress(false),
mDurationUs(-1),
mPositionUs(-1),
mSeekInProgress(false),
mLooper(new ALooper),
mPlayerFlags(0),
mAtEOS(false),
mLooping(false),
mAutoLoop(false) {
ALOGV("NuPlayerDriver(%p)", this);
mLooper->setName("NuPlayerDriver Looper");

mLooper->start(
false, /* runOnCallingThread */
true,  /* canCallJava */
PRIORITY_AUDIO);

mPlayer = AVNuFactory::get()->createNuPlayer(pid);
mLooper->registerHandler(mPlayer);

mPlayer->setDriver(this);
}


主要部分:

mLooper(new ALooper),
mLooper->start(
false, /* runOnCallingThread */
true,  /* canCallJava */
PRIORITY_AUDIO);
mLooper->registerHandler(mPlayer);


  其中mLooper(new ALooper) 和mLooper->start创建一个线程,该线程不断地执行mLooper的loop函数,每执行一次loop函数就会从线程中由mLooper维护的事件链表取出首端事件,然后判断该事件的时间戳,如果该事件的时间戳小于或者等于当前系统的时间,则调用该事件消息的deliver函数将该事件的消息派发出去。

  现在完成了这样一个创建,还没有向事件链表中添加任何事件。

下面贴出mLooper调用registerHandler函数的具体流程


==>
mLooper->registerHandler(mPlayer);

==>
ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) {
return gLooperRoster.registerHandler(this, handler);
}

==>
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, looper);

return handlerID;
}

==>
handler->setID(handlerID, looper);

==>
inline void setID(ALooper::handler_id id, wp<ALooper> looper) {
mID = id;
mLooper = looper;
}


  由ALooper调用其registerHandler函数来完成注册,整个注册过程除了将ALooper和AHandler绑定成一对儿,然后给予一个唯一的键值,存储在全局对象gLooperRoster的mHandlers容器中,还通过调用handler->setID(handlerID, looper)将这个键值和 looper的引用保存在handler中。

  将键值和 looper的引用保存在handler中这很重要,因为只有拥有ALooper的引用,才能调用ALooper提供的post接口将事件添加到ALooper维护的事件链表中。

  这样以来,一个经过注册的AHandler对象,将拥有一个非零的键值用来标识自己和与自己绑定在一起的ALooper对象,并且该AHandler对象含有该ALooper对象的引用,后续会通过这个引用来调用ALooper对象的post接口向ALooper对象维护的事件链表中。

1.2创建一个消息

==>
void NuPlayer::start() {
(new AMessage(kWhatStart, this))->post();
}

==>
AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
: mWhat(what),
mNumItems(0) {
setTarget(handler);
}

==>
void AMessage::setTarget(const sp<const AHandler> &handler) {
if (handler == NULL) {
mTarget = 0;
mHandler.clear();
mLooper.clear();
} else {
mTarget = handler->id();
mHandler = handler->getHandler();
mLooper = handler->getLooper();
}
}

==>
struct AHandler : public RefBase {
wp<ALooper> getLooper() const {
return mLooper;
}

wp<AHandler> getHandler() const {
// allow getting a weak reference to a const handler
return const_cast<AHandler *>(this);
}
};


  创建消息的时候需要两个参数,一个是消息名,另一个是经过注册的消息处理者(AHandler),this这里是NuPlayer对象,也是前面的创建的mPlayer,是一个AHandler对象。

  设置好了消息名后,然后调用setTarget(handler)函数,设置mTarget,mHandler,mLooper这些成员变量的值。其中mHandler和mLooper是一对儿经过注册的AHandler,ALooper对儿,mTarget是标识这一对儿的键值。

  整个流程完成赋值后,形成的格局是:

  有一对儿绑定在一起的AHandler,,ALooper跟据标识这一对儿的键值存储在全局对象gLooperRoster的mHandlers容器中。

  然后这个经过注册的A
4000
Handler对象作为参数值来创建一个消息AMessage对象。这个AMessage对象通过传递的AHandler对象得到了这个AHandler对象的引用,并且获取到了他的handler ID 和ALooper对象的引用。

  这样以来这个AMessage对象和AHandler对象都拥有了ALooper对象的引用引用,这样就可以通过调用ALooper对象的post函数来向ALooper对象维护的事件链表中添加事件。同时AMessage对象也拥有了AHandler对象的引用,这样就可以调用AHandler对象的函数来对该消息进行处理。

1.3发用消息

==>
void NuPlayer::start() {
(new AMessage(kWhatStart, this))->post();
}

==>
status_t AMessage::post(int64_t delayUs) {
sp<ALooper> looper = mLooper.promote();
if (looper == NULL) {
ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
return -ENOENT;
}

looper->post(this, delayUs);
return OK;
}

==>
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);
}


  通过调用该AMessage对象拥有的ALooper对象引用调用其post函数来向ALooper对象维护的事件链表添加消息。

1.4消息派发(deliver)

==>
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());
}

event.mMessage->deliver();

// 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;
}

==>
event.mMessage->deliver();

==>
void AMessage::deliver() {
sp<AHandler> handler = mHandler.promote();
if (handler == NULL) {
ALOGW("failed to deliver message as target handler %d is gone.", mTarget);
return;
}

handler->deliverMessage(this);
}


  通过AMessage对象拥有的AHandler对象的引用,然后调用AHandler对象对象的deliverMessage函数将消息派发出去。

1.5消息处理

==>
handler->deliverMessage(this);

==>
namespace android {

void AHandler::deliverMessage(const sp<AMessage> &msg) {
onMessageReceived(msg);
mMessageCounter++;

if (mVerboseStats) {
uint32_t what = msg->what();
ssize_t idx = mMessages.indexOfKey(what);
if (idx < 0) {
mMessages.add(what, 1);
} else {
mMessages.editValueAt(idx)++;
}
}
}

}  // namespace android

==>
onMessageReceived(msg);


  handler->deliverMessage函数里调用了onMessageReceived(msg);

  onMessageReceived在AHandler里是纯虚函数,NuPlayer继承自AHandler并且重写了onMessageReceived。所以通过虚函数机制最终是在NuPlayer的onMessageReceived函数里对msg进行处理的

  下面贴出安卓N版本AHandler.h的原文

#ifndef A_HANDLER_H_

#define A_HANDLER_H_

#include <media/stagefright/foundation/ALooper.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>

namespace android {

struct AMessage;

struct AHandler : public RefBase {
AHandler()
: mID(0),
mVerboseStats(false),
mMessageCounter(0) {
}

ALooper::handler_id id() const {
return mID;
}

sp<ALooper> looper() const {
return mLooper.promote();
}

wp<ALooper> getLooper() const {
return mLooper;
}

wp<AHandler> getHandler() const {
// allow getting a weak reference to a const handler
return const_cast<AHandler *>(this);
}

protected:
virtual void onMessageReceived(const sp<AMessage> &msg) = 0;

private:
friend struct AMessage;      // deliverMessage()
friend struct ALooperRoster; // setID()

ALooper::handler_id mID;
wp<ALooper> mLooper;

inline void setID(ALooper::handler_id id, wp<ALooper> looper) {
mID = id;
mLooper = looper;
}

bool mVerboseStats;
uint32_t mMessageCounter;
KeyedVector<uint32_t, uint32_t> mMessages;

void deliverMessage(const sp<AMessage> &msg);

DISALLOW_EVIL_CONSTRUCTORS(AHandler);
};

}  // namespace android

#endif  // A_HANDLER_H_


2.总结

  整体来说安卓N版本里异步消息处理机制较安卓M版本有了很大的变化,不过涉及到的还是ALooper,AHandler,AMessage这三个。只不过在实现机理上有了不小的变化。

  我觉得N版本这个实现机理上还是比较好的,但是容易绕糊涂。

  对这个版本的实现机理做个小结:

  ALooper提供post函数用来向事件链表里添加消息,AHandler提供函数deliverMessage来完成消息派发。两个函数调用都是发生在AMessage提供的post和deliver函数里的。因此问题的关键就是这个中间者需要拥有ALooper,AHandler的引用这样就可以在自己的post和deliver函数里里分被调用ALooper提供的post函数和AHandler提供函数deliverMessage来完成事件的添加和消息的派发。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ALooper AHandler AMessage
相关文章推荐