什么是Handler
- Handler允许您发送和处理与线程MessageQueue关联的Message和Runnable对象,每个Handler的实例都与一个线程的MessageQueue相关联,当你创建一个新的Handler时,它将被绑定到创建它的线程的MessageQueue,从绑定时起它可以将Message和Runnable对象传递给该MessageQueue并在需要执行这些Message或Runnable时处理这些消息。
Handler 的作用
Handler有两个主要用途:
- 用来指定Message和Runnable将要执行的时间点(例如延迟几秒后执行)
- 用来将其它线程要求此线程执行的消息放入MessageQueue中并在需要的时候执行(线程间通讯)
Handler源码解析
-
Handler运行过程中主要对象有两个,一个MessageQueue(消息队列),另一个Looper(消息循环),前者作用是存储handler将要处理的消息,后者则是在MessageQueue有消息时取出交给Handler处理。
Looper与MessageQueue初始化
- 首先我们来看Looper与MessageQueue来源:handler有7个构造函数,但我们只需要看其中两个主要的构造函数:
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
/**
* callback:handler处理函数的回调
* async:是否为异步消息
**/
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
以上展示的是Handler的两个主要构造函数,在其中我们看到mLooper的初始化,一个是通过Looper.myLooper获取Looper实例,另一个通过参数的方式传递进来。
-
Looper.myLooper作用是获取当前线程的Looper实例,当Looper为空时会抛出 Looper.prepare()未调用 异常,因此在子线程中创建Handler有两种方法(主线程在初始化时已经自动调用过Looper.prepare()方法,所以主线程没有手动创建Looper时不会报错)
- 调用第二个构造函数传入Looper实例;
- 调用第一个构造函数之前调用Looper.perpare() 创建Looper实例。 注意:若是想要handler正常工作则还需在创建handler之后调用Looper.loop();
-
MessageQueue的初始化则是调用looper.mQueue(),Looper中的MessageQueue则会在调用Looper.perpare时初始。
Handler消息调度
-
Handler可以通过以下7个方法发送消息:
- post(Runnable)
- postAtTime(Runnable,long)
- postDelayed(Runnable,long)
- sendEmptyMessage(int)
- sendMessage(Message)
- sendMessageAtTime(Message,long)
- sendMessageDelayed(Message,long)
-
上述7个方法其实最终都会调用下述方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
上述方法首先会将handler自身赋值给Message中的target变量,判断是否为异步消(异步消息不受同步屏障影响),最后会调用MessageQueue的enqueue(Message,long)将Message放入消息队列中,至此handler中的消息发送完成。
Handler消息处理
- Looper.loop方法中会不停在MessageQueue中取出消息,同时会通过Message.target调用Handler的dispatchMessage(Message)方法,将此条消息交给Handler处理
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
此方法首先会判断Message中CallBack是否不为空,通过此判断当前接收的是Message还是Runnable消息,若是Runnable则会调用runnable的run方法,若不是则会先判断CallBack是否为空,若为空则直接调用Handler的handleMessage方法处理消息,若不为空则会调用CallBack的handleMessage处理消息,并通过返回值判断是否继续调用Handler的handlerMessage继续处理消息,至此Handler的消息处理流程完成。
总结
- 通过上述流程我们可以看出不管Handler是发送消息,还是接收使用的MessageQueue都是同一个,因此在不同线程通过handler发送的消息都是保存在同一份内存中,而Looper.loop()方法则会在创建Handler的线程中通过调用Handler的dispatchMessage分发消息给Handler处理,以此实现了跨线程的传递。