android 消息处理框架,Android Native层异步消息处理框架

一、前言

在NuPlayer中,可以发现许多类似于下面的代码:

cdec0645add3fc3c328197dda5c76203.png

81178cc93a2a3bb5048d90d76e7ec935.png

1 //=======================================//2 NuPlayerDriver::NuPlayerDriver(pid_t pid)3 : ......4 mLooper(newALooper)5 ......{6 mLooper->setName("NuPlayerDriver Looper");7 mLooper->start(8 false, /*runOnCallingThread*/

9 true, /*canCallJava*/

10 PRIORITY_AUDIO);11

12 mPlayer = newNuPlayer(pid);13 mLooper->registerHandler(mPlayer)14 }15

16 //=======================================//17 sp msg = new AMessage(kWhatPerformSeek, this);18 msg->setInt32("generation", ++mSeekGeneration);19 msg->setInt64("timeUs", seekTimeUs);20 status_t err = msg->postAndAwaitResponse(&response);21

22 //=======================================//23 void NuPlayer::RTSPSource::onMessageReceived(const sp &msg) {24 switch(what) {25 caseXXX:26 caseYYY:27 ......28 default:29 }30 }

View Code

这就是android在native层实现的一个异步消息处理机制,在这个机制中所有的处理都是异步的。其基本的处理流程可概述如下:

将变量封装到一个消息AMessage结构体中,然后放到消息队列中去,后台专门有一个线程会从这个队列中取出消息并发送给指定的AHandler处理,在handler的onMessageReceived函数中根据AMessage的mWhat字段转向对应的分支进行处理。

在这里我们可能会产生这样的疑问:在很多类中都会有各种消息post出来,而后台的异步消息处理线程又是怎么知道将一个消息发送给哪个类的onMessageReceived函数处理呢?

要搞明白这个问题,就需要分析android在native层的异步消息处理框架。

二、基础类分析

在android native层的异步消息处理框架中涉及到的类主要有:ALooper、AHandler、AMessage、ALooperRoster、LooperThread等。

1、AMessage -- 消息的载体

结构体AMessage是消息的载体,在传递消息的过程中可以携带各种信息。

cdec0645add3fc3c328197dda5c76203.png

81178cc93a2a3bb5048d90d76e7ec935.png

1 //AMessage类简析

2 struct AMessage : publicRefBase {3 //构造函数,在其中会对AMessage的两个重要数据成员mWhat和mTarget进行初始化设置。

4 AMessage();5 AMessage(uint32_t what, const sp &handler);6 void setWhat(uint32_t what);//设置mWhat

7 uint32_t what() const;//返回mWhat

8 void setTarget(const sp &handler);//设置mTarget9 //一系列的set和find函数,用于在传递消息的过程中携带各种信息

10 void setInt32(const char *name, int32_t value);11 void setInt64(const char *name, int64_t value);12 //....

13 bool findInt32(const char *name, int32_t *value) const;14 bool findInt64(const char *name, int64_t *value) const;15 //投递消息到消息队列中

16 status_t post(int64_t delayUs = 0);17 //Posts the message to its target and waits for a response (or error) before returning.

18 status_t postAndAwaitResponse(sp *response);19 protected:20 virtual ~AMessage();//析构函数

21 private:22 friend struct ALooper; //deliver()23 //两个重要的私有数据成员:24 //mWhat指明这是一个什么消息,用于在onMessageReceived处理分支中进行匹配。25 //mTarget用于后台线程在处理这个消息时判断发送给哪一个类处理。

26 uint32_t mWhat;27 ALooper::handler_id mTarget;28

29 wpmHandler;30 wp mLooper;

View Code

进一步分析AMessage对象的构造函数,首先我们查看AMessage的source code,如下:

cdec0645add3fc3c328197dda5c76203.png

81178cc93a2a3bb5048d90d76e7ec935.png

1 AMessage::AMessage(uint32_t what, const sp &handler)2 : mWhat(what),3 mNumItems(0) {4 setTarget(handler);5 }6

7 void AMessage::setTarget(const sp &handler) {8 if (handler ==NULL) {9 mTarget = 0;10 mHandler.clear();11 mLooper.clear();12 } else{13 mTarget = handler->id();14 mHandler = handler->getHandler();15 mLooper = handler->getLooper();16 }17 }

View Code

在构造函数中设置mWhat的值为指定的what值,用于指明这是一个什么消息,以便在onMessageReceived函数中找到匹配的分支进行处理。然后会调用setTarget函数,来设置mTarget为指定handler的mID值,mHandler为指定的handler,mLooper为与handler相关的ALooper,这样后台处理线程就可以据此判断将该消息发送给哪一个类(handler)进行处理了。

构造消息并投递出去的过程,如下示例:

1 voidNuPlayer::start() {2 (new AMessage(kWhatStart, this))->post();3 }

2、ALooper类

这个类定义了消息循环和后台处理线程。

cdec0645add3fc3c328197dda5c76203.png

81178cc93a2a3bb5048d90d76e7ec935.png

1 //ALooper类简析

2 struct ALooper : publicRefBase {3 //定义的两个整型变量类型

4 typedef int32_t event_id;//event id

5 typedef int32_t handler_id;//handler id

6

7 ALooper();//构造函数8

9 //Takes effect in a subsequent call to start().

10 void setName(const char *name);11

12 handler_id registerHandler(const sp &handler);//注册handler

13 void unregisterHandler(handler_id handlerID);//注销handler14 //启动后台处理线程处理事件

15 status_t start(16 bool runOnCallingThread = false,17 bool canCallJava = false,18 int32_t priority =PRIORITY_DEFAULT19 );20 protected:21 virtual ~ALooper();22 private:23 friend struct AMessage; //post()24 //事件的结构体封装

25 structEvent {26 int64_t mWhenUs;27 spmMessage;28 };29 AString mName;30 ListmEventQueue;31 structLooperThread;32 sp mThread;//后台处理线程33 //posts a message on this looper with the given timeout

34 void post(const sp &msg, int64_t delayUs);35 boolloop();36 }

View Code

3、LooperThread

4、AHandler -- 消息处理类的父类

AHandler类用于对接收到的消息进行对应的处理。下面我们结合source code进行分析如下:

cdec0645add3fc3c328197dda5c76203.png

81178cc93a2a3bb5048d90d76e7ec935.png

1 struct AHandler : publicRefBase {2 AHandler() //构造函数

3 : mID(0), //初始化mID为0

4 mVerboseStats(false),5 mMessageCounter(0) {6 }7

8 ALooper::handler_id id() const {//这个函数用于返回内部变量mID的值,其初始值为0,但是可以通过setID()设置

9 returnmID;10 }11

12

13 protected:14 virtual void onMessageReceived(const sp &msg) = 0;15

16 private:17 friend struct AMessage; //deliverMessage()

18 friend struct ALooperRoster; //setID()

19

20 ALooper::handler_id mID;21 wpmLooper;22 //setID()在其友元类ALooperRoster的registerHandler()函数中调用。

23 inline void setID(ALooper::handler_id id, wplooper) {24 mID =id;25 mLooper =looper;26 }27

28 };

View Code

5、ALooperRoster类

ALooperRoster可以看做是ALooper的一个辅助类,主要用于完成消息handler的注册与注销工作。下面结合source code分析如下:

三、异步消息处理框架

首先我们先copy一段代码来看一看异步消息处理框架的搭建过程:

1 spmLooper;2 mLooper(new ALooper)//构造函数的初始化列表中

3 mLooper->setName("NuPlayerDriver Looper");4 mLooper->start(false, true, PRIORITY_AUDIO);5 mPlayer = new NuPlayer;//struct NuPlayer : public AHandler

6 mLooper->registerHandler(mPlayer);

搭建框架1

调用ALooper的构造函数,实例化一个新的ALooper对象:

1 ALooper::ALooper()2 : mRunningLocally(false) {3 //clean up stale AHandlers. Doing it here instead of in the destructor avoids4 //the side effect of objects being deleted from the unregister function recursively.

5 gLooperRoster.unregisterStaleHandlers();6 }

搭建框架2

调用ALooper::setName(const char *name)设置ALooper的名字:

1 void ALooper::setName(const char *name) {2 mName =name;3 }

搭建框架3

调用ALooper::start()启动异步消息处理后台线程:

1 status_t ALooper::start(2 bool runOnCallingThread, boolcanCallJava, int32_t priority) {3 //......

4

5 if (mThread != NULL ||mRunningLocally) {6 returnINVALID_OPERATION;7 }8 mThread = new LooperThread(this, canCallJava);//构造LooperThread对象

9 status_t err = mThread->run( //run()之后就会执行LooperThread::threadLooper()函数,在threadlooper()函数中又会调用ALooper::loop()函数10 mName.empty() ? "ALooper": mName.c_str(), priority);11 if (err !=OK) {12 mThread.clear();13 }14 returnerr;15 }

搭建框架4

调用ALooper::registerHandler()注册消息处理器类AHandler:

1 ALooper::handler_id ALooper::registerHandler(const sp &handler) {2 return gLooperRoster.registerHandler(this, handler);3 }

从这个函数的定义可以看出,能作为handler进行注册的类都必须继承自AHandler这个类,注册的过程也是交给了gLooperRoster处理的。

原文:http://www.cnblogs.com/roger-yu/p/5856507.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值