Android消息机制

来源:互联网 发布:朴素贝叶斯分类算法 编辑:程序博客网 时间:2024/06/08 19:33

作者:Debbie

在Android程序运行中,线程之间或者线程内部进行信息交互时经常会使用到消息,在分析Android消息机制之前,我们先了解与消息有关的几个类:



1.Message

消息对象,顾名思义就是记录消息信息的类。消息对象,包含了一些描述信息和数据。这个类有几个比较重要的字段:

a.arg1和arg2:我们可以使用两个字段用来存放我们需要传递的整型值,在Service中,我们可以用来存放Service的ID。

b.obj:该字段是Object类型,我们可以让该字段传递某个多项到消息的接受者中。

c.what:这个字段可以说是消息的标志,在消息处理中,我们可以根据这个字段的不同的值进行不同的处理,类似于我们在处理Button事件时,通过switch(v.getId())判断是点击了哪个按钮。

在使用Message时,我们可以通过new Message()创建一个Message实例,但是Android更推荐我们通过Message.obtain()或者 Handler.obtainMessage()获取Message对象。这并不一定是直接创建一个新的实例,而是先从消息池中看有没有可用的Message实例,存在则直接取出并返回这个实例。反之如果消息池中没有可用的Message实例,则根据给定的参数new一个新Message对象。通过分析源码可得知,Android系统默认情况下在消息池中实例化10个Message对象。

2.MessageQueue

消息队列,用来存放Message对象的数据结构,按照“先进先出”的原则存放消息。存放并非实际意义的保存,而是将Message对象以链表的方式串联起来的。MessageQueue对象不需要我们自己创建,而是有Looper对象对其进行管理,一个线程最多只可以拥有一个MessageQueue。我们可以通过Looper.myQueue()获取当前线程中的MessageQueue。

3.Looper

MessageQueue的管理者,负责为当前线程运行一个消息循环(MessageQueue)。它会循环抽取MessageQueue中的Message,并通过handler对象将其分发并处理。在一个线程中,如果存在Looper对象,则必定存在MessageQueue对象,并且只存在一个Looper对象和一个MessageQueue对象。在Android系统中,除了主线程有默认的Looper对象,其它线程默认是没有Looper对象。如果想让我们新创建的线程拥有Looper对象时,我们首先应调用Looper.prepare()方法,然后再调用Looper.loop()方法。

4.Handler

负责消息对象的传递与处理,。通过Handler对象我们可以封装Message对象,然后通过sendMessage(msg)把Message对象添加到 MessageQueue中;当MessageQueue循环到该

Message时,就会调用该Message对象对应的handler对象的 handleMessage()方法对其进行处理。使用该类时我们必须先继承Handler类,然后重写Handler类中的handlerMessage(msg)方法,在此方法中进行相关处理操作,如:更新UI



消息机制的完整流程:

1.生成消息

Message msg =handler.obtainMessage() / Message.obtain()

注意:虽然Message有公有的构造方法,但是建议还是使用上面写的这两种方法。因为,在调用这两个方法时,会去对象池中获取可重复利用的Message对象,避免了重新创建。

2.发送消息

handler.sendMessage(msg);  或者 message.sendToTarget();   (它其实内部也是调用了handler.sendMessage(msg)方法)。通过分析代码来探究下“发送消息”这个操作的内部机制:




 上面的这个方法,其实只是做了两个操作:       

1. 将当前对象(handler)保存在message.target我们知道中, 方便在处理消息对象时使用。

2. 将message对象存入到MessageQueue(入队)。 其实 MessageQueue 类似于我们的链表结构,我们入队的Message对象遵循“先进先出”的原则,越早被入队的Message,会被越早处理。       

该方法中出现的MessageQueue从何而来呢?从sendMessageAtTime()可知, 将message入队到MessageQueue对象实际上是 Handler 类中一个成员变量 : mQueue  。它是在Handler的构造放被初始化的, MessageQueue 对象 实际是位于Looper类中,在构造handler对象的时候,我们从Looper中取出,并将其赋值给handle类中的成员变量。“发送消息”这个操作的内部操作:通过调用handler.sendMessage(msg) 方法,将传入的message对象传入到Looper对象(此对象唯一关联一个线程对象)的消息队列(MessageQueue)当中,等待被处理。

3. 执行消息

在第二步操作中我们已经知道,消息对象已经被handler发送到Looper中的MessageQueue中了。那么接下来该Message对象又做了什么呢?它最终又是怎么被执行的呢?

首先,我们先在Looper的源码中找到存放的消息对象的MessageQueue



传入的Looper类中MessageQueue中的消息对象又是怎么执行的呢?




通过查看上面的源码我们看到,Looper类中有一个Loop() 方法,它里面维护了一个死循环,负责抽取该类中的MessageQueue中的消息对象,然后该消息对象被对应的handler对象,传到 handler 对象中的dispatchMessage方法中。 源码如下:




在此处方法中只是回调了handler.handlerMessage(msg)方法, 该处理方法默认为空。 所以,如果我们要对message进行的处理的话,必须继承Handler类然后重写handlerMessage方法,来完成自己的处理。

通过上述分析,Android的消息机制已经大概明白了,其过程如下:

1.生成消息(生成Message对象)

   2.发送消息(消息入队)

3.执行消息(Loop()方法将Message从消息队列中抽取出并传递到与Message相关的handler对象中)