AMessage

基础数据结构定义:

struct AMessage : public RefBase {

    AMessage();

    AMessage(uint32_t what, const sp<const AHandler> &handler);

private:

    friend struct ALooper; // deliver()

    uint32_t mWhat;  

    // used only for debugging

    ALooper::handler_id mTarget;

    wp<AHandler> mHandler;

    wp<ALooper> mLooper;

struct Item {

        union {

            int32_t int32Value;

            int64_t int64Value;

            size_t sizeValue;

            float floatValue;

            double doubleValue;

            void *ptrValue;

            RefBase *refValue;

            AString *stringValue;

            Rect rectValue;

        } u;

        const char *mName;

        size_t      mNameLength;

        Type mType;

        void setName(const char *name, size_t len);

    };

    enum {

        kMaxNumItems = 64

    };

    Item mItems[kMaxNumItems];  //amessage里面最多可以放64个数据

    size_t mNumItems;


具体实现

void AMessage::Item::setName(const char *name, size_t len) {

    mNameLength = len;

    mName = new char[len + 1];

    memcpy((void*)mName, name, len + 1);

}

取数据,

const AMessage::Item *AMessage::findItem(

        const char *name, Type type) const {

    size_t i = findItemIndex(name, strlen(name));

    if (i < mNumItems) {

        const Item *item = &mItems[i];

        return item->mType == type ? item : NULL;

    }

    return NULL;

}

要是u里面直观类型

bool AMessage::findAsFloat(const char *name, float *value) const {

    size_t i = findItemIndex(name, strlen(name));

    if (i < mNumItems) {

        const Item *item = &mItems[i];

        switch (item->mType) {

            case kTypeFloat:

                *value = item->u.floatValue;

                return true;

            case kTypeDouble:

                *value = (float)item->u.doubleValue;

                return true;

            case kTypeInt64:

                *value = (float)item->u.int64Value;

                return true;

            case kTypeInt32:

                *value = (float)item->u.int32Value;

                return true;

            case kTypeSize:

                *value = (float)item->u.sizeValue;

                return true;

            default:

                return false;

        }

    }

    return false;

}

存string,string内容是拷贝过去的

void AMessage::setString(

        const char *name, const char *s, ssize_t len) {

    Item *item = allocateItem(name);

    item->mType = kTypeString;

    item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);

}


amessage,abuffer,object这些是存指针

void AMessage::setObjectInternal(

        const char *name, const sp<RefBase> &obj, Type type) {

    Item *item = allocateItem(name);

    item->mType = type;

    if (obj != NULL) { obj->incStrong(this); }

    item->u.refValue = obj.get();

}

void AMessage::setObject(const char *name, const sp<RefBase> &obj) {

    setObjectInternal(name, obj, kTypeObject);

}

void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {

    setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);

}

void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {

    Item *item = allocateItem(name);

    item->mType = kTypeMessage;

    if (obj != NULL) { obj->incStrong(this); }

    item->u.refValue = obj.get();

}

取buffer等对象,是直接取到原先的强指针

bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const {

    const Item *item = findItem(name, kTypeBuffer);

    if (item) {

        *buf = (ABuffer *)(item->u.refValue);

        return true;

    }

    return false;

}

bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {

    const Item *item = findItem(name, kTypeMessage);

    if (item) {

        *obj = static_cast<AMessage *>(item->u.refValue);

        return true;

    }

    return false;

}


消息发送

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;

    }

在Alooper的mEventQueue消息队列中,是按timeUs进行排序的

1)一般使用方式

sp<AMessage> notify = mNotify->dup();

        notify->setInt32("what", kWhatInformSender);

        notify->setInt64("avgLatencyUs", avgLatencyUs);

        notify->setInt64("maxLatencyUs", maxLatencyUs);

        notify->post();


接收方

case kWhatInformSender:

        {

            int64_t avgLatencyUs;

            CHECK(msg->findInt64("avgLatencyUs", &avgLatencyUs));

            int64_t maxLatencyUs;

            CHECK(msg->findInt64("maxLatencyUs", &maxLatencyUs));


2) 需要响应,:awaitResponse(const sp<AReplyToken> &replyToken, sp<AMessage> *response)

token是消息发送方填入,response是接收方响应后填入


看到AMessage里面的token

status_t AReplyToken::setReply(const sp<AMessage> &reply) {

    if (mReplied) {

        ALOGE("trying to post a duplicate reply");

        return -EBUSY;

    }

    CHECK(mReply == NULL);

    mReply = reply;

    mReplied = true;

    return OK;

}

bool retrieveReply(sp<AMessage> *reply) {

        if (mReplied) {

            *reply = mReply;

            mReply.clear();

        }

        return mReplied;

    }

要结合ALooper里面看,在ALooper里面对replytoken进行设置,消息回复时postReply设置reply,条件condition通知awaitResponse触发收到reply

// to be called by AMessage::postAndAwaitResponse only

status_t ALooper::awaitResponse(const sp<AReplyToken> &replyToken, sp<AMessage> *response) {

    // return status in case we want to handle an interrupted wait

    Mutex::Autolock autoLock(mRepliesLock);

    CHECK(replyToken != NULL);

    while (!replyToken->retrieveReply(response)) {

        {

            Mutex::Autolock autoLock(mLock);

            if (mThread == NULL) {

                return -ENOENT;

            }

        }

        mRepliesCondition.wait(mRepliesLock);

    }

    return OK;

}

status_t ALooper::postReply(const sp<AReplyToken> &replyToken, const sp<AMessage> &reply) {

    Mutex::Autolock autoLock(mRepliesLock);

    status_t err = replyToken->setReply(reply);

    if (err == OK) {

        mRepliesCondition.broadcast();

    }

    return err;

}

====================================

struct ALooper::LooperThread : public Thread {

    LooperThread(ALooper *looper, bool canCallJava)

        : Thread(canCallJava),

          mLooper(looper),

          mThreadId(NULL) {

    }

ALooper是起线程

ALooper::loop() {  //不停循环 发送消息

mEventQueue.erase(mEventQueue.begin());

event.mMessage->deliver();


//post是将消息放到发送队列里面,如果当前队列为空,则会signal唤醒loop()函数中等待,linux的边缘触发

void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) {

    if (it == mEventQueue.begin()) {

        mQueueChangedCondition.signal();

    }

    mEventQueue.insert(it, event);


消息如何响应处理

、、、

bool ALooper::loop() {

    Event event;

    {

        Mutex::Autolock autoLock(mLock);

        if (mThread == NULL && !mRunningLocally) {

            return false;

        }

        if (mEventQueue.empty()) {

            //当前没有消息处理,等待唤醒,唤醒后直接return

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

    }

  //deliver才是让AMessage对应的Hander来进行处理

    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;

}

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

}

、、、

总结下android的消息机制,就是amessage->post加入到ALooper的mEventQueue List 队列,然后 

ALooper线程不停looper来进行处理,从mEventQueue List取出一个个AMessage,根据保存的Handler对象,调用Handler的子类对象来真正处理消息,没看到有消息积压这类告警和提示

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,699评论 0 3
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,825评论 0 38
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,034评论 0 2
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,725评论 0 9
  • 作为AMessage/ALooper/AHandler中最复杂的一环, AMessage被我放到了最后来讲. 希望...
    TankWitch阅读 3,959评论 0 1