Android消息机制的理解

来源:互联网 发布:郭天祥单片机教程 编辑:程序博客网 时间:2024/06/03 22:51

前言:该文章是本人以前查阅了很多消息机制的文章及自己在这块的理解汇总而来的,基本是比较全的了,之前网上的一些文章有些缺漏这里都一一作了修改和补充,需要学习android消息机制的朋友,这篇收藏版文章可以帮助到你。

一.消息处理机制中的一些基本概念
Google参考了Windows的消息处理机制,在Android系统中实现了一套类似的消息处理机制。学习Android的消息处理机制,有几个概念(类)必须了解:

  1. Message
    消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程。
  2. Message Queue
    消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
  3. Handler
    Handler是Message的主要处理者,负责将Message添加到消息队列以及对消息队列中的Message进行处理。
    其中sendMessage()方法是将消息发送到消息队列中
  4. Looper
    循环器,扮演Message Queue和Handler之间桥梁的角色,循环取出Message Queue里面的Message,并交付给相应的Handler进行处理。
    5. 线程
    UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。

每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类来接收Looper所送出的消息。

二.在主线程中Looper和MessageQueue的理解

这里写图片描述

在Android的主线程创建好的时候,会在主线程中创建如上图中的两个重要的实例,轮询器和消息队列对象

Looper和MessageQueue
运行机理:
每个线程都可以并仅可以拥有一个Looper实例,消息队列MessageQueue在Looper的构造函数中被创建并且作为成员变量被保存,也就是说MessageQueue相对于线程也是唯一的。Android应用在启动的时候会默认会为主线程创建一个Looper实例,并借助相关的Handler和Looper里面的MessageQueue完成对Activities、Services、Broadcase Receivers等的管理。而在子线程中,Looper需要通过显式调用Looper. Prepare()方法进行创建。Prepare方法通过ThreadLocal来保证Looper在线程内的唯一性,如果Looper在线程内已经被创建并且尝试再度创建”Only one Looper may be created per thread”异常将被抛出。
小结:
1. 主线程创建好就会创建Looper对象和MessageQueue对象,而后者在前者的类中执行;
2. 子线程要创建Looper则需要显示调用Looper.Prepare()创建,一个线程对应一个Looper(无论主线程还是子线程)

Handler与Looper的关系:
Handler在创建的时候可以指定Looper,这样通过Handler的sendMessage()方法发送出去的消息就会添加到指定Looper里面的MessageQueue里面去。在不指定Looper的情况下,Handler绑定的是创建它的线程的Looper。如果这个线程的Looper不存在,程序将抛出”Can’t create handler inside thread that has not called Looper.prepare()”。
小结:哪个线程创建了Handler对象,那么Handler默认就会使用该线程下的Looper对象,如果线程不存在Looper对象就会报错,当然可以指定Handler使用哪个线程的Looper对象

整个消息处理的大概流程是:
1. 包装Message对象(指定Handler、回调函数和携带数据等);2. 通过Handler的sendMessage()等类似方法将Message发送出去;3. 在Handler的处理方法里面将Message添加到Handler绑定的Looper的MessageQueue;4. Looper的loop()方法通过循环不断从MessageQueue里面提取Message进行处理,并移除处理完毕的Message;5. 通过调用Message绑定的Handler对象的dispatchMessage()方法完成对消息的处理。

在dispatchMessage()方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:1. Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;2. Handler里面mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;3. 处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息

三.编程角度去理解消息机制的处理
这里写图片描述
总结:
1.android通过一种消息机制来刷新页面:大部分操作,事件都是最终通过产生消息来通知界面的。
2.对消息队列的操作只能通过Handler来进行:
2.1:当调用Handler的sendMessage()的方法就能够插入一个消息
2.2:主线程的Looper会发现消息队列的改变,并响应这个消息
2.3:消息被处理完以后会从队列中被移除

如何响应消息?(handler的handleMessage()方法在主线程中运行,而Looper可以在主线程也可以在子线程中)
通过handler发布消息,那个Handler也会作为处理者调用消息:
1.处理的过程包含调用Handler的handleMessage()方法(通过Looper对象去调用的)
2.通过重写handleMessage()方法来实现对这个消息的处理
3.这个方法是运行在主线程中的
4.轮询器可以在主线程,也可以在子线程,不指定默认在主线程

message 和handler的关系分析:
1.Looper和MessageQueen在主线程创建的时候,就会被创建;想在子线程中创建Looper轮询器,需要通过显式调用Looper. Prepare()方法进行创建
2.一般我们并不直接访问这两个对象
3.Handler必须在有Looper实例的情况下才能实例化
(也就是说,一般不会在子线程中去创建Handler的对象)
4.子线程默认是没有实例化Looper和MessageQueen的动作的
(默认在主线程中实例化Looper和MessageQueen)

以上就是全部内容,大家可以自个去试试,有什么问题可以留言。或者在微信公众号“技术帮团队”上找我们。

0 0
原创粉丝点击