Android消息循环分析

我们的常用的系统中,程序的工作通常是有事件驱动和消息驱动两种方式,在Android系统中,Java应用程序是靠消息驱动来工作的。

消息驱动的原理就是:
1. 有一个消息队列,可以往这个队列中投递消息;
2. 有一个消息循环,不断从消息队列中取出消息,然后进行处理。
在Android中通过Looper来封装消息循环,同时在其中封装了一个消息队列MessageQueue。
另外Android给我们提供了一个封装类,来执行消息的投递,消息的处理,即Handler。

在我们的线程中实现消息循环时,需要创建Looper,如:

1class LooperThread extends Thread { 2 public Handler mHandler; 3 public void run() { 4 Looper.prepare(); //1.调用prepare 5 ...... 6 Looper.loop(); //2.进入消息循环 7 } 8}

看上面的代码,其实就是先准备Looper,然后进入消息循环。

  1. 在prepare的时候,创建一个Looper,同时在Looper的构造方法中创建一个消息队列MessageQueue,同时将Looper保存到TLV中(这个是关于ThreadLocal的,不太懂,以后研究了再说)
  2. 调用loop进入消息循环,此处其实就是不断到MessageQueue中取消息Message,进行处理。

然后再看我们如何借助Handler来发消息到队列和处理消息

Handler的成员(非全部):

1final MessageQueue mQueue; 2final Looper mLooper; 3final Callback mCallback;

Message的成员(非全部):

1Handler target; 2Runnable callback;

可以看到Handler的成员包含Looper,通过查看源代码,我们可以发现这个Looper是有两种方式获得的,1是在构造函数传进来,2是使用当前线程的Looper(如果当前线程无Looper,则会报错。我们在Activity中创建Handler不需要传Handler是因为Activity本身已经有一个Looper了),MessageQueue也就是Looper中的消息队列。

然后我们看怎么向消息队列发送消息,Handler有很多方法发送队列(这个自己可以去查),比如我们看sendMessageDelayed(Message msg, long delayMillis)

1public final boolean sendMessageDelayed(Message msg, long delayMillis) { 2 if (delayMillis < 0) { 3 delayMillis = 0; 4 } 5 return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); 6// SystemClock.uptimeMillis() 获取开机到现在的时间 7} 8 //最终所有的消息是通过这个发,uptimeMillis是绝对时间(从开机那一秒算起) 9public boolean sendMessageAtTime(Message msg, long uptimeMillis) { 10 boolean sent = false; 11 MessageQueue queue = mQueue; 12 if (queue != null) { 13 msg.target = this; 14 sent = queue.enqueueMessage(msg, uptimeMillis); 15 } 16 return sent; 17}

看上面的的代码,可以看到Handler将自己设为Message的target,然后然后将msg放到队列中,并且指定执行时间。

消息处理

处理消息,即Looper从MessageQueue中取出队列后,调用msg.target的dispatchMessage方法进行处理,此时会按照消息处理的优先级来处理:

  1. 若msg本身有callback,则交其处理;
  2. 若Handler有全局callback,则交由其处理;
  3. 以上两种都没有,则交给Handler子类实现的handleMessage处理,此时需要重载handleMessage。

我们通常采用第三种方式进行处理。

注意!!!!我们一般是采用多线程,当创建Handler时,LooperThread中可能还未完成Looper的创建,此时,Handler中无Looper,操作会报错。

我们可以采用Android为我们提供的HandlerThread来解决,该类已经创建了Looper,并且通过wait/notifyAll来避免错误的发生,减少我们重复造车的事情。我们创建该对象后,调用getLooper()即可获得Looper(Looper未创建时会等待)。

补充

本文所属为Android中java层的消息循环机制,其在Native层还有消息循环,有单独的Looper。并且2.3以后MessageQueue的核心向Native层下移,native层java层均可以使用。这个我没有过多的研究了!哈哈

PS:本文参考《深入理解Android:卷I》

原文地址:http://blog.isming.me/blog/2014/04/02/android-message-loop-analyze/ ,转载请注明出处。

点赞
收藏

评论区

加载中...

相关推荐

Centos7安装RabbitMQ详细教程 - 附带软件基本解释 - CSDN博客

MQ引言什么是MQMQ:messageQueue翻译为消息队列,通过典型的生产者和消费者模型不断向消息队列中生产消息,消费者不断从队列中获取消息。因为消息的生产和消费都是一部的,而且只关心消息的发送和接收,没有业务逻辑的侵入,轻松的实现了系统之间的解耦。别名是消息中间件,通过利用高效的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系

Redis 发布订阅模式(7)

列表的局限前面我们说通过队列的rpush和lpop可以实现消息队列(队尾进队头出),但是消费者需要不停地调用lpop查看List中是否有等待处理的消息(比如写一个while循环)。为了减少通信的消耗,可以sleep()一段时间再消费,但是会有两个问题:1、如果生产者生产消息的速度远大于消费者消费消息的速度,List会占用大量的内存。2、

Handler更新UI的几种方式

Handler、loop、MessageQueue的工作原理Message:Handler接收和处理的消息对象Looper:每个线程只能拥有一个looper.它的loop方法负责读取MessageQueue中的消息,读到信息之后就把消息返回给handler处理MessageQueue:消息队列。程序创建Looper对象时,会在它的构造器中创建

RabbitMq学习笔记——概念

1、RabbitMQ简介  MQ全称为MessageQueue(消息队列),是一种“应用程序”<—“应用程序”的通信方法。MQ是一个典型的“消费”<—“生产者”模型的代表,生成者往消息队列中写入消息,消费者从消息队列中读取消息。2、MQ的应用场景  对于一个大型的软件系统来说,它会有很多的组件或者说模块或者说子系统或者

Android的消息循环与Handler机制理解

一、概念1、事件驱动型什么是事件驱动?就是有事了才去处理,没事就躺着不动。假如把用户点击按钮,滑动页面等这些都看作事件,事件产生后程序就执行相应的处理方法,就是属于事件驱动型。2、消息循环把需要处理的事件表示成一个消息,并且把这个消息放入一个队列。消息循环就是一循环,for或者while都一样。从消息队列里面取出未处理的消息,然后调用该消息的

SpringBoot日记——MQ消息队列整合(一)

  除了之前讲到的缓存,我们还会用到消息队列来存储一些消息,为了提升系统的异步性能等等;  消息服务有两个概念需要知道:消息代理messagebroker,目的地destination。消息发送由代理接管并传递到指定目的地:    ——消息只有唯一的发送和接受者,消息从队列中取出就不在了。  目的地有两种形式:queue\点对点的消息队