什么是Handler消息机制?
Android中为我们定义好的一套线程间数据共享与通信的框架。它包含一套完整的数据结构定义(Handler、Looper、Message、MessageQueue)和调用逻辑。
Handle类的作用:
在新启动的线程中发送消息。
在主线程中获取,处理消息
类角色简要描述(Java层)
Handler:使用接口,发送消息到消息队列,重写方法处理消息
Message:消息数据的封装
Looper:线程本地变量,完成消息循环
MessageQueue:消息队列,存放消息,并与底层交互
工作模型简述
Handler将消息发送到MessageQueue消息队列中
Looper对消息队列进行管理,从消息队列中进行取消息
取出的消息由对应的Handler进行分发和处理
为什么需要Handler消息机制?
线程间数据共享与通信
Android的单线程UI模型
有序操作
消息循环
我们可以调用Looper类的loop函数使线程进入到一个消息循环中。之后就不断地去消息队列中获取消息:
如果有消息需要处理就将消息返回处理;
如果没有消息需要处理就会通过JNI调用C++层的pollInner函数进行睡眠等待。
线程处于睡眠状态又是如何被唤醒的呢?
在创建C++层的Looper的时候,会创建一个管道,管道其实就是个文件,用于进程间通信;
将这个管道的读端文件描述符和写端文件描述符保存到该Looper的成员变量中;
最后对管道注册监听事件。
出来清空管道。之后Looper就会将消息取出,实现消息循环。不是我们所关心的事件,如果是就会唤醒Looper所在的线程,并将管道内容读取出来清空管道。之后Looper就会将消息取出,实现消息循环。
消息发送
调用Handler的成员函数来发送一个Message或Runnable对象。在发送消息时,是可以指定消息的处理时间的,如果没有指定默认为立即处理。
Handler的内部成员变量mQueue将消息放入消息队列中,在放入队列之前将发送消息的Handler赋给Message的变量target。
把消息加入到消息队列时,根据消息的处理时间进行排序:
当加入的消息在目标消息队列头部时,执行唤醒操作;
当加入的消息在目标消息队列中间时,不需要唤醒线程。
当需要唤醒线程时,我们通过在C++层的Looper向写端文件描述符写入一个字符,我们在前面已经注册了管道的监听事件,所以这个时候目标线程就会因为这个管道 发生了一个事件而被唤醒
消息处理
消息从MessageQueue中取出后,会交给target的dispatchMessage函数分发。
前面我们知道消息的成员变量target指向的是一个Handler对象,所以就调用Handler的dispatchMessage分发消息。
Handler类的成员函数dispatchMessage按照以下顺序来分发一个消息:
Handler发送一个Runnable对象时msg.callback不为空,之后handleCallback函数就会调用Runnable的run函数。
mCallback是Handler内部接口Callback的实现类的对象,一般为null。否则调用该接口的handleMessage函数。
如果前面两个条件都不满足,最后调用Handler的handleMessage,一般由子类重写。