Android-Handler消息机制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android-Handler消息机制相关的知识,希望对你有一定的参考价值。

参考技术A Handler在android中负责调度消息并将来某个时段处理消息。Android有大量的消息驱动方式来进行交互,比如四大组件的的启动过程的交互,都离不开消息机制。

消息机制涉及MessageQueue/Message/Looper/Handler这4个类。

Message:消息分为硬件产生的消息(如按钮、触摸)和软件生成的消息;

MessageQueue:消息队列的主要功能向消息池投递消息和取走消息池的消息;

Handler:消息辅助类,主要功能向消息池发送各种消息事件(Handler.sendMessage)和处理相应消息事件(Handler.handleMessage);

Looper:不断循环执行(Looper.loop),按分发机制将消息分发给目标处理者。

这里是通过Looper中的myLooper方法来获得Looper实例的,如果Looper为null的话就会抛异常,抛出的异常内容翻译过来就是无法在未调用 Looper.prepare()的线程内创建handler,new handler的时候没有报错那么就一定之前就调用了 Looper.Prepare(),在哪里创建的呢?

答案在 ActivityThread.main() 中。

ActivityThread 的 main()方法就是整个APP的入口,也就是我们通常所讲的主线程, UI线程。但他实际上并不是一个线程,ActivityThread 并没有继承 Thread 类,我们可以把他理解为主线程的管理者,负责管理主线程的执行,调度等操作,看下main方法的源码。

两个关键方法 Looper.prepareMainLooper()和Looper.loop(),loop方法后面再分析,继续看prepareMainLooper的方法内部如下:

到1⃣️这里就解决了,为什么我们在主线程中使用Handler之前没有调用Looper.prepare方法的问题了,就是在这里调用了prepare 方法。
2⃣️prepare方法内部把 Looper 放到ThreadLocal中与当前线程绑定,保证一个线程只有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
3⃣️在Looper的构造函数中始化MessageQueue

所以初始化Handler之前Looper 和 MessageQueue就已经初始化了,并把Looper放到ThreadLocal中。ThreadLocal有个特点是你set进去的值是以当前所处的线程为key,value就是你set的值。源码如下:

先看一下sendMessage的流程图:

简单过一遍,sendXXX 这些方式最终还是会调用到 enqueueMessage 这个方法上来的逻辑最后调用queue.enqueueMessage 添加消息到消息队列MessageQueue中,下面就是消息的入队逻辑

消息入队顺序是按照 Message 触发时间 long when入队的,有新消息加入时,会循环遍历当前消息队列,对比消息触发时间,直到找到当前消息合适的插入位置,以此来保证所有消息的触发时间顺序。即 MessageQueue 添加消息到消息队列中。

Handler把Message交给MessageQueue并存储起来 ,那么谁来负责把我这里的消息分发出去并且告诉主线程的人(Handler)呢?答案就是 Looper 了!

之前分析的ActivityThread.main()中的Looper.loop还没有讲到我们接着跟进去看一下源码

loop()不断从MessageQueue中取消息,把消息交给target(handler)的dispatchMessage方法处理。下面是dispatchMessage

可以看到dispatchMessage最后调用了handleMessage方法,在源码里面是个空实现。需要我们在创建handler的时候复写,根据不同的message处理不同的业务逻辑。

整个Handler的消息分发调度流程就讲完了,为了增强记忆,我再把整个流程拼成一块如下图:

Android的handler机制的原理?

Android的handler机制的原理分为异步通信准备,消息发送,消息循环,消息处理。

1、异步通信准备

在主线程中创建处理器对象(Looper)、 消息队列对象(Message Queue)和Handler对象。

2、消息入队

工作线程通过Handler发送消息(Message) 到消息队列(Message Queue)中。

3、消息循环

消息出队: Looper循环取出消息队列(Message Queue) 中的的消息(Message)。

消息分发: Looper将取出的消息 (Message) 发送给创建该消息的处理者(Handler)。

4、消息处理

处理者(Handler) 接收处理器(Looper) 发送过来的消息(Message),根据消息(Message) 进行U操作。

handler的作用

handler是android线程之间的消息机制,主要的作用是将一个任务切换到指定的线程中去执行,(准确的说是切换到构成handler的looper所在的线程中去出处理)android系统中的一个例子就是主线程中的所有操作都是通过主线程中的handler去处理的。

Handler的运行需要底层的 messagequeue和 looper做支撑。



参考技术A   Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。

  一、Handler的定义:
  主要接受子线程发送的数据, 并用此数据配合主线程更新UI。
  解释:当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件, 进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如: 联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭"。 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的, 也就是说,更新UI只能在主线程中更新,子线程中操作是危险的。 这个时候,Handler就出现了。,来解决这个复杂的问题 ,由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。
  二、Handler一些特点
  handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),它有两个作用:
  (1)安排消息或Runnable 在某个主线程中某个地方执行;
  (2)安排一个动作在不同的线程中执行。
  三、Handler实例
  子类需要继承Hendler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据。
参考技术B andriod提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。  1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。  2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。    3) Message Queue(消息队列):用来存放线程放入的消息。  4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。本回答被提问者和网友采纳

以上是关于Android-Handler消息机制的主要内容,如果未能解决你的问题,请参考以下文章

Android-Handler同步屏障

如何实现消息机制

Android消息机制和原理

消息机制

windows程序消息循环机制

windows消息机制是怎么一回事?谢谢!