Handler机制

Handler机制

Hanlder相关

Handler在Android中的主要作用是用于线程间通信。Handler机制有几个关键的对象,Looper,MessageQueue,Message.

  • Message Hanlder用来接收和处理的对象。
  • MessageQueue 消息队列在初始化Looper对象时会创建一个与之关联的MessageQueue,里面的消息按时间先后来排序,遵从先进先出原则。。
  • Looper 循环者,每个线程只能够有一个Looper,Looper负责创建并管理当前线程中的MessageQueue,调用Looper.loop()方法之后,就会进入一个无限循环中,不断的从MessageQueue中取出Message并分发给对应的Handler,最后通过Handler的handleMessage()方法来处理此消息
Hanlder工作原理

Hanlder在初创建的时候,在其构造方法中通过Looper.myLooper();得到当前线和的Looper对象,并通过该对象得到Looper中的MessageQueue,当使用Handler的所有发送消息的方法中,我们跟踪源码进去可以看到最终都是调用enqueueMessage()这个方法

1
2
3
4
5
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//将Message的target设置为当前Handler对象
if (mAsynchronous) msg.setAsynchronous(true);
return queue.enqueueMessage(msg, uptimeMillis);//将消息放到消息队列中。
}

当Looper调用Looper.loop方法的时候就会进入一个死循环,循环中调用MessageQueue的next方法得到一个Message对象,然后通过message.target得到将这个消息放入到队列中的hanlder对象,然后调用Handler的dispatchMessage()方法分发出来,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next();
if (msg != null) {
if (msg.target == null) {
quit message.
return;
}
msg.target.dispatchMessage(msg);
msg.recycle();
}
}
}

在dispatchMessage先获得该消息的callback成员变量以及Hanlder的mCallback成员变量,一般这两个变量都会为空,于是就会调用handleMessage()方法来处理这个消息。

1
2
3
4
5
6
7
8
9
10
11
12
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
Looper 原理

Looper类中先申明了一个ThreadLocal的线程内部的数据存储对象类,通过它可以在指定线程中存储数据,数据存储之后,也只有在指定线程中可以获取到存储的数据。

1
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

Looper构造方法中创建出当前线程的MessageQueue,并将成员变量赋什为当前线程

1
2
3
4
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}

通过调用prepare()方法,创建一个当前线程的Looper对象作为ThreadLocal的成员变量。

1
2
3
4
5
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));

通过调用myLooper()方法得到当前线程的Looper对象

1
2
3
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}

调用loop方法开始执行循环并分发消息。