FROM:http://blog.sina.com.cn/s/blog_49f62c350101gts9.html

正如其他GUI应用程序一样,Android应用程序也是消息(事件)驱动的。这种消息的传递必须依赖于应用框架提供的消息机制。Android本身提供了2种消息机制:

组件间消息传递--- Intent

线程间消息传递--- Message

本文主要讨论Android线程间消息传递机制及其应用。


1.Android Message机制

所谓消息机制,就是实现消息传递、消息分发、消息处理的一套程序逻辑,一般属于应用程序框架的功能范围。应用程序开发者可以利用应用程序框架提供的消息API来开发应用。典型的消息APISendMessage(),PostMessage(),HandleMessage(),DispatchMessage().同理,Android Message机制也提供了类似API,其内部实现机制也跟其他平台一样,基于消息队列。但是AndroidMessage都是异步处理的。

1.1 消息传递

Android Message机制的消息队列采用单链表结构。

Message机制及其应用" title="AndroidMessage机制及其应用" height="42" width="576">

其中mMessages是头指针,m1, m2, m3..Message节点。每个Android消息都有个相对开机时间的过期时间,消息队列是基于这个过期时间先后顺序排序的,需要尽快处理的消息排在前面。所以其插入算法是:

Message机制及其应用" title="AndroidMessage机制及其应用" height="308" width="529">

参考代码:\frameworks\base\core\java\android\os\MessageQueue.java@enqueueMessage()

1.2 消息分发

Android 设计了一个死循环来负责消息的分发, 它不停的从消息队列获取过期的消息,一旦取得,就调用该message对应的handler去处理。由于消息队列是基于消息过期时间排序的。所以该分发函数的实现逻辑非常简单,每次只是判断第1个节点对应的消息是否过期,如果过期,则从链表取走(删除),并分发给该消息对应的handler去处理,处理之后回收该消息结构;如果没有过期的消息,则block自己一段时间(可能消息队列里没有消息了) 主要实现逻辑如下:

Message机制及其应用" title="AndroidMessage机制及其应用" height="575" width="539">

参考代码:\frameworks\base\core\java\android\os\Looper.java@loop()

\frameworks\base\core\java\android\os\MessageQueue.java@next()

其中msg.target是预先设置的消息处理handler。每个消息都一个对应的handler,handler负责分发或默认处理消息。msg.recycle()负责把用完的消息结构回收,以便复用该结构。

1.3 消息处理

跟其他平台的消息机制一样,Android也提供了接口供用户注册/创建自己的消息处理方法,同时也支持消息携带特定的处理函数,因此Android的消息处理更加灵活。

基本逻辑如下:

Message机制及其应用" title="AndroidMessage机制及其应用" height="334" width="493">
参考代码:\frameworks\base\core\java\android\os\Handler.java@dispatchMessage()

2. Message相关的类

Android Message机制中用到以下几个重要类:

Looper,MessageQueue,Message,Handler

它们之间的关系是

Message机制及其应用" title="AndroidMessage机制及其应用" height="323" width="554">

2.1 Message

该类负责Message对象的创建/回收/销毁,对应一个特定的消息。维护一个可用消息链表用于回收用完的消息结构(最大size10)。

参考代码:frameworks\base\core\java\android\os\Message.java

2.2 MessageQueue

该类实现Message队列,它是个单链表结构,提供链表的插入/删除/检索操作。外部可以利用特定函数对消息进行链表操作。它总是被Looper创建,与Looper是一对一的关系。

参考代码:\frameworks\base\core\java\android\os\MessageQueue.java

2.3 Looper

该类实现消息的定时分发,属于消息机制的核心机构。它负责轮询消息队列,找出过期的消息并分发特定handler进行处理。因此一个Looper必须有一个MessageQueue

参考代码:\frameworks\base\core\java\android\os\Looper.java

2.4 Handler

该类实现消息的发送以及处理,负责发送用户消息以及调用用户注册的callback或接口进行消息处理。因此每个消息肯定有一个对应的handler,否则消息无法被发送/处理。

参考代码:\frameworks\base\core\java\android\os\Handler.java

2.5 ThreadLocal

该类存储Thread相关的数据。此处用于存储与Thread关联的Looper实例。这样每个Thread都可以有自己的消息队列以及消息处理方式。

2.6 Callback

该类是一个接口,用户在创建Handler实例时可以传入该interface实例,这样一旦消息到来,handler会调用该接口来处理。

2.7 Runnable

该类也是一个接口,用户可以向特定的Runnable发送消息,一旦成功,该Runnable会被调用。一旦某个消息指定了自己的callback(Runnable), 那么该消息将交给它的callback去处理,不会交给HandlerCallback接口或HandlerhandleMessage()处理。

在实际应用中,它们有如下的调用关系:

Message机制及其应用" title="AndroidMessage机制及其应用" height="222" width="558">

3. Thread的关系

1Android 应用程序默认只有1Process,但可以有多个Thread

1Android 应用程序对应1ActivityThread实例, 它就是应用的主线程(UI 线程)

系统默认为主线程创建了1个消息循环(Looper),并启动它开始接收消息

其他线程默认没有Looper,所以没有 MessageQueue,不能接收Message, 如果需要接收Message, 则需要通过Looper.prepare()创建一个MessageQueue

1个线程只能有1Looper, 也就是说只能有1MessageQueue

1个线程可以有多个Handler, 多个Runnable, 多个Callback


4. Message
机制的应用

4.1 子线程向主线程发送消息

主线程中所做的操作最好耗时非常短,一般建议创建子线程去完成比较费时的工作(访问网络,下载数据,查询数据库等),以免主线程阻塞而发生ANR异常。但子线程通常不能更新UI,异常android.view.ViewRoot$CalledFromWrongThreadException:Onlythe original thread that created a view hierarchy can touch itsviews。所以子线程与主线程需要通过Message来沟通信息。这个场景很常见。实现逻辑如下:

主线程创建Handler实例
privateHandler mHandler = new Handler(new Handler.Callback() {

public boolean handleMessage(Message msg){

switch (msg.what) {
case UPDATE_UI:

{
//updateUI

break;
}
default:
break;
}});


子线程利用主线程的
Handler
向主线程发送消息:
MessagenotifyMsg = mHandler.obtainMessage(UPDATE_UI, 60, 100, null);
mHandler.sendMessage(notifyMsg) ;


4.2 主线程向子线程发送消息

子线程创建自己的
Handler
实例并建立消息Looper

class subThread extends Thread{

public void run() {

Looper.prepare();

mSubThreadHandler= new Handler(){

public void handleMessage(Message msg) {

Log.e(sTag, (String)msg.obj);

}

};

Looper.loop();

}

}


主线程利用子线程的
Handler
向子线程发送消息:

Message cmdMsg =mSubThreadHandler.obtainMessage(CMD_STOP, 0, 0, null);mSubThreadHandler.sendMessage(cmdMsg);


4.3 Runnable发送消息

可以通过Handler直接发送消息来运行某个Runnable。这种方式更像用消息机制实现一个Timer来完成某个工作。Runnable运行在Handler所在的线程中,单次执行。

mHandler.post(new Runnable(){

public void run() {

//do something

}

});

由于ThreadRunnable的子类,也可以这样使用:

Thread myThread = new Thread(){

public void run() {

//do something

}

};

mHandler.post(myThread);

注意此时并不会启动一个线程,跟上面的runnable方式一样,run()会运行在Handler所在的线程中,本质上就等同于Handler调用myThread.run(), 就是一个普通调用,所以不会新开一个线程。


更多相关文章

  1. IPC(Inner Process Comunication)机制基本了解
  2. Android(安卓)framework 系统服务的启动流程
  3. Android(安卓)UI线程与子线程
  4. Android(安卓)更新UI的两个方法
  5. Android(安卓)Tcp服务器端
  6. android之listView缓存机制
  7. 多线程例子 android camera capture
  8. android创建通知栏(java版)
  9. Android学习笔记(7)————Android中的消息机制

随机推荐

  1. PHP使用递归按层级查找数据(代码详解)
  2. PHP+jQuery开发简单翻牌抽奖的功能(代码实
  3. PHP利用PHPExcel导出数据到Excel
  4. PHP-Curl模拟HTTPS请求(代码实例)
  5. PHP 超全局变量之$_FILES详解
  6. PHP 跨域之header函数(代码示例)
  7. 如何保证消息队列的高可用?
  8. PHP识别文件伪装(文件上传)
  9. PHP中Trait的用法及示例
  10. php基础知识考察点之正则表达式