安卓异步消息处理机制ALooperRoster

本文详细解析了Android N版本中ALooperRoster类的结构及其实现,包括其构造函数、registerHandler和unregisterHandler函数的具体逻辑,有助于理解Android消息循环机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.安卓N版本ALooperRoster.h原文

#ifndef A_LOOPER_ROSTER_H_

#define A_LOOPER_ROSTER_H_

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

namespace android {

struct ALooperRoster {
    ALooperRoster();

    ALooper::handler_id registerHandler(
            const sp<ALooper> looper, const sp<AHandler> &handler);

    void unregisterHandler(ALooper::handler_id handlerID);
    void unregisterStaleHandlers();

    void dump(int fd, const Vector<String16>& args);

private:
    struct HandlerInfo {
        wp<ALooper> mLooper;
        wp<AHandler> mHandler;
    };

    Mutex mLock;
    KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers;
    ALooper::handler_id mNextHandlerID;

    DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster);
};

}  // namespace android

#endif  // A_LOOPER_ROSTER_H_

1.1条件编译

#ifndef A_LOOPER_ROSTER_H_

#define A_LOOPER_ROSTER_H_

...
...
...

#endif  // A_LOOPER_ROSTER_H_

条件编译宏,防止该头文件被重复包含而导致的重复定义。

1.2包含的头文件

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

包含了定义ALooperRoster.h所需要引用的文件。

1.3名字空间

namespace android {

...
...
...

}

2.成员变量

private:
    struct HandlerInfo {
        wp<ALooper> mLooper;
        wp<AHandler> mHandler;
    };

    Mutex mLock;
    KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers;
    ALooper::handler_id mNextHandlerID;

2.1struct HandlerInfo

    struct HandlerInfo {
        wp<ALooper> mLooper;
        wp<AHandler> mHandler;
    };
该结构提有有两个域,这两个域就是绑定在一起的一对儿ALooperAHandlerKeyedVector<ALooper::handler_id, HandlerInfo>是用来存放很多这样的ALooperAHandler对儿。每一对儿有唯一的键值:ALooper::handler_id

注意:该键值是唯一的,由ALooper::handler_id mNextHandlerID来计数,从1开始计数,每有一对儿这样的ALooper,AHandler对儿进行注册,则该值就自增1。

3.ALooperRoster的实现

3.1构造函数的实现

下面贴出安卓N版本下ALooperRoster的构造函数

ALooperRoster::ALooperRoster()
    : mNextHandlerID(1) {
}

很简单,就是将mNextHandlerID计数器的值置为1,表示从1开始计数,每有一对儿ALooper,AHandler进行注册,当前该值作为该ALooper,AHandler对儿的键值标识,然后将该值自增1.

3.2registerHandler函数的实现

下面贴出安卓N版本下registerHandler函数的实现

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

可以看出传进来的参数哦是一对儿ALooper,AHandler的引用,并且AHandler的id()返回值必须要为0,这是因为定义0表示未注册,当完成注册后将mNextHandlerID的值赋给AHandler的mID.

从下面两行代码可以看出。
ALooper::handler_id handlerID = mNextHandlerID++;
handler->setID(handlerID, looper);
这个时候AHandler的mID就不为0了,表示已经注册过。

3.3unregisterHandler函数的实现

下面贴出安卓N版本下unregisterHandler函数的实现

void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
    Mutex::Autolock autoLock(mLock);

    ssize_t index = mHandlers.indexOfKey(handlerID);

    if (index < 0) {
        return;
    }

    const HandlerInfo &info = mHandlers.valueAt(index);

    sp<AHandler> handler = info.mHandler.promote();

    if (handler != NULL) {
        handler->setID(0, NULL);
    }

    mHandlers.removeItemsAt(index);
}

可以看到传入的参数是表示一对儿ALooper,AHandler的键值,该键值保存在注册成功后的AHandler的mID中。

ssize_t index = mHandlers.indexOfKey(handlerID);
即使用键值来找到对应的ALooper,AHandler存放的索引。

const HandlerInfo &info = mHandlers.valueAt(index);即通过索引找到该ALooper,AHandler的引用,也即HandlerInfo结构体的引用。

if (handler != NULL) {
    handler->setID(0, NULL);
}

如果handler不为空则调用handler->setID将其mID置为0,表示未经注册过。

mHandlers.removeItemsAt(index);
通过索引来移除当前这对儿ALooper,AHandler。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值