三者关系:
a.Runnable和Message可以被压入MessageQueue中,形成一个集合。其中一般情况下某种类型的MessageQueue只允许相同类型的object,实际需要先对Runnable进行转换。
b.Looper循环做某件事情,如果队列为空,则休眠。
c.Handler为处理事情,对传进来的各种object进行相应的处理。
总而言之就是Looper不断的去获取MessageQueue中的某个Message,然后交给Handler处理
1、Handler
源码路径:frameworks/base/core/java/android/os/Handler.java
Handler和Thread的关系:
每个Thread只对应一个Looper;每个Looper只对应一个MessageQueue;每个MessageQueue中有个多个Message;每个Message中最多指定一个Handler来处理事件。
由此得出Thread和Handler是一对多的关系
Handler主要的作用有两点,一点是处理Message,第二点是将某个Message压入MessageQueue中。
Looper取出一个Message后,会调用Handler.dispatchMessage进行消息分发,handleMessage处理消息。
默认情况下的派发流程是:
message.classback(Runnable对象) 是否为空,不为空的情况下,优先通过callback来解决
Handler.mCallback是否为空,不为空的情况下,调用mCallback.handleMessage
如果前两个对象都不存在,则调用Handler.handleMessage
由此,Handler的扩展子类可以通过重载dispatchMessage或者handleMessage来改变他的默认行为。
相关的功能函数post和Send都是负责将某个消息压入MessageQueue中;区别在于后者处理的函数参数是Message,post需要先把其他类型额消息转换成Message,再调用send函数执行下一步。
因为调用者提供的是Runnable对象,post需要先将其封装成一个Message,接着通过对应的send函数把它推送到MessageQueue中。
public final boolean post(){
return sendMessageDelayed(getPostMessage(r),0);
}
private static Message getPostMessage(Runnable r){
Message m = Message.obtain();//Android系统会维护一个全局的Message池,当使用Message时,可以通过obtain直接获得,而不是自行创建。可以减少不必要的资源浪费
m.callback = r;//将Runnable对象设置为Message的回调函数
return m;
}
当准备好Message后,调用sendMessageDelayed来执行下一步。其内部有通过延长时间再发送消息。
public boolean sendMessageAtTime(Message msg,long uptimeMillis){
MessageQueue queue = mQueue;//Handler对应的消息队列
if(queue == null){
//正常情况下,每个Thread都会有一个MessageQueue来承载消息,除非发生了意外queue才会空
RuntimeException e = new RuntimeException(this+"sendMessageAtTime() called with no mQueue");
Log.w("Looper",e.getMessage(),e);
return false;
}
return enqueueMessage(queue,msg,uptimeMillis);//将此消息压入MessageQueue
}
这样就将一条由Runnable组成的Message通过Handler压入了MessageQueue中。
2、MessageQueue
源码路径:frameworks/base/core/java/android/os
具备队列的所有常规操作包括:
a.新建队列,由其构造函数和本地方法nativeInit组成。
其中,nativeInit会在本地创建一个NativeMessageQueue对象,然后直接赋给MessageQueue中的成员变量。
b.元素入队
final boolean enqueueMessage(Message msg,long when);
c.元素出队
final Message next();
d.删除元素
final void removeMessages(Handler h,int what,Object object);
final void removeMessages(Handler h,Runnable r,Object object);
f.销毁队列
通过本地函数nativeDestory销毁
3、Looper
源码路径:frameworks/base/core/java/android/os
用于给线程提供一个消息队列(MessageQueue),并且实现循环等待。
应用程序使用Looper有两种情况:
主线程:AndroidThread
普通线程:LooperThread
class LooperThread extends Thread{
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler(){
public void handleMessage(Message msg){
//处理消息的地方
}
};
Looper.loop();//进入主循环
}
}
以上代码只有三个步骤:
a.Looper的准备工作(prepare)
b.创建处理消息的handler
c.Looper开始运作(loop)
Looper中有个重要的成员变量
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
这是一个静态变量,一旦import了Looper后,sThreadLocal就已经存在并构建完毕。ThreadLocal只是它所在线程的全局变量,意味着每个线程的Looper都是独立的。
Looper和Handler的关联是通过构造函数,因为Handler内部有许多内部变量需要初始化比如:
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
public Handler(){
mLooper = Looper.myLooper();//通过sThreadLocal.get来获取当前线程中的Looper实例
mQueue = mLooper.mQueue;//mQueue是Looper与Handler之间沟通的桥梁
mCallback = null;
}
后续Handler执行Post/Send两个系列的函数时,会将消息投递到mQueue也就是mLooper.mQueue中。一旦Looper处理到这一个消息时,它又会从中调用Handler来进行处理。