3 Alooper分析
来源:互联网 发布:淘宝模特培训 编辑:程序博客网 时间:2024/06/16 07:59
概述
这里介绍下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;}
从mHandlers中找到已经注册过的对应的ALooper对象,并调用post方法
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中转,完成了消息的传递。
【结束】
- 3 Alooper分析
- Multimedia Alooper 机制分析
- libstagefright 框架设计分析 (1): ALooper, AHandler
- Android Media Player 框架分析-AHandler AMessage ALooper
- ②NuPlayer播放框架之ALooper-AHandler-AMessage底层机制分析
- android native ALooper AHandler
- 安卓异步消息处理机制ALooper
- nrgrep函数分析(3)--搜索实现分析
- Mikrokopter MK 代码分析3-uart分析
- 3、Android音频系统分析--音频策略分析
- Fatfs文件系统分析(3)-底层接口分析
- Android Framework 分析---3PackageManager 分析
- linphone 分析3 打电话源码分析
- CASSINI源代码分析(3)
- 词法分析(3)---DFA
- vivi源代码分析3
- 3GP文件格式分析
- 可执行文件分析(3)
- NSString字符串的实际应用
- HDU 2952 Counting Sheep (深度搜索)
- spring技术翻译开始
- OCP-1Z0-051-V9.02-91题
- 获取JAVA当前进程PID的两种方法
- 3 Alooper分析
- Android:NDK r9
- 手游2dx面试笔记一
- enq: TX - row lock contention
- 整型数组处理算法(三)把一个数组里的所有元素,插入到另一个数组的指定位置
- 输出1到最大的N位数
- 每个程序员都该知道的10大编程格言
- Linux协议栈代码阅读笔记(一)
- 一般函数指针和类的成员函数指针