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

2 篇文章 0 订阅
2 篇文章 0 订阅

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容器中。
  然后这个经过注册的AHandler对象作为参数值来创建一个消息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来完成事件的添加和消息的派发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值