概述#
类 | 说明 |
---|---|
Handler | 真正处理事件的地方 |
Looper | 循环检查是否有要传输的事件,从 MessageQueue 中获取事件,并交给 Handler 处理(假如列队为空就进入休眠) |
MessageQueue | 储存需要做的事情,一般来说只允许保存相同类型的 Object、Message 除存的数据结构队列 |
Message | 需要做的事件 |
一个 Thread 对应一个 Looper
一个 Looper 对应一个 MessageQueue
一个 MessageQueue 内有多个 Message
每个 Message 中最多对应一个 Handler 处理事件
Thread & Handler 是一对多的关系
Handler#
接受处理 Messgae
将 Message 存入 MessageQueue 中
// Handler.java
public class Handler {
...
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;
...
public interface Callback {
boolean handleMessage(@NonNull Message msg);
}
// 通常用来给使用者 Override 处理事件
public void handleMessage(@NonNull Message msg) {
}
// 分化,有三种方式
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
}
在上面分发事件有三种方法,并且 这三种分发方式有先后顺序,只要前面被处理,就不会使用后面的方式处理
Message 本身的 callback
实现 Callback 接口
Override Handler#handleMessage
Function
通过 Handler 把信息入队到 MessageQueue,方式有 Post & Send 两种系列,并且可以控制发送的时间
Post 系列:把零散信息转为 Message 再用 Send 传出
函数 | 功能 |
---|---|
boolean post(Runnable r) | 直接发出信息 |
boolean postAtTime(Runnable, long updatetimeMillis) | 在固定(规定)时间再发出该条信息 |
Send 系列:参数直接是 Message |
函数 | 功能 |
---|---|
boolean sendEmptyMessage(int what) | 直接发送信息 |
boolean sendMessageArFrontOfQueue(Message msg) | 把消息发送到信息队列最前面 |
boolean sendMessageAtTime(int what, long updatetimeMillis) | 在固定(规定)时间再发出该条信息 |
boolean sendMessageDelayed(Message msg, long delayMillis) | 延迟几毫秒后发送该信息 |
Post 实现方式
// Handler.java
public class Handler {
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
// 包装 callback 再传出
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain(); // 取得 Message 资源,避免不断创建,可以复用资源
m.callback = r; // 直接设定 Runnable 回调函数
return m;
}
// 最后通过计算 当前时间 + 延长实现,之后就呼叫 sendMessageAtTime 函数
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
// 在规定时间发送信息
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
// 若是该 Thread 并没有规定 MessageQueue 则会抛出错误
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
}
发送信息方法#
名称 | 参数:回传 | 解释 |
---|---|---|
post | Runnable : boolean | 接收一个 Runnable 对象作为 Message |
postAtTime | Runnable, long : boolean | 接收一个 Runnable 对象作为 Message,并在等待的规定时间发送 Message |
sendEmptyMessage | int : boolean | 发送一个使用者规定的 int 信息,在由使用者自己处理 |
sendMessageAtTime | Messge, int : boolean | 发送一个使用者规定的 int 信息,在由使用者自己处理 |
sendMessageDelayed | Messge, long : boolean | 在等待的规定时间后 (延迟) 发送 Message |
Post & Send#
// Send ...
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
// Post ...
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
// 最终都会 sendMessageAtTime
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) { // 1.
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
处理 Message#
从 dispatchMessage 可看出它预设处理 Message 的顺序
msg.callback (Runnable)
mCallback (interface)
handleMessage (method)
public void handleMessage(Message msg) {
// 使用者复写
}
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
// callback 优先级最高
if (msg.callback != null) { // msg.callback is Runnable
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
MessageQueue & Message#
如其名,它是一个队列 FIFO,它通过 本地方法 (Native) 内存指针创建 Queue
private native static long nativeInit();
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
Queue 方法#
名称 | 参数:回传 | 解释 |
---|---|---|
enqueueMessage | Message, long : boolean | 在指定时间内压入队列中 |
next | void : Message | 元素拉出队列 |
removeMessages | Handler, int, Object : void | 移除特定元素 |
removeMessages | Handler, Runnable, Object : void | 移除特定元素 |
MessageQueue#
MessageQueue 因为是 Queue 所以有所谓的 FIFO, 所以有队列的功能
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
private native static int nativeInit();
MessageQueue 创建#
连接于 Looper 的建构函数,当 Looper 创建时 MessageQueue 就一同创建
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Looper 通过 MessageQueue 取得 Message#
// MessageQueue.java
Message next() {
// 若已经被 depose mPtr 就会被设定为 0
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
// 下一个信息的时间
int nextPollTimeoutMillis = 0;
// 进入无限循环,也就是说 next 会导致 block
for (;;) {
... 省略部分
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null; // 上一个信息
Message msg = mMessages; // 当前信息
if (msg != null && msg.target == null) { // target 就是 Handler
// 找到一个可发送的 Message
do {
prevMsg = msg;
msg = msg.next; // 切换到下一个 Message
} while (msg != null && !msg.isAsynchronous());
}
// 再次判断 Message
if (msg != null) {
// 判断时间
if (now < msg.when) { // 该信息的时间还没到
// Next message is not ready. Set a timeout to wake up when it is ready.
// 计算剩余时间
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 时间到,并且有 Message
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next; // 上一个 Message 就是当前 Message
} else {
mMessages = msg.next; //切换到下一个要用的 Message
}
// 断开连接 !! 好让 GC 侦测到后回收 !!! (可达性分析)
msg.next = null;
... debug 訊息
msg.markInUse(); // 标记该 Message 已经被使用过
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) { // 检查是否退出
dispose();
return null;
}
... 省略 IdleHandler
}
... 省略部分
}
IdleHandler#
IdleHandler 是 MessageQueue 内的一个 interface,它可以在 MessageQueue 没有消息时让使用者知道,并决定如何处理
// MessageQueue.java
public static interface IdleHandler {
// 返回true,会让你设定的接口继续存在
// 返回false则会移除你设定的接口
boolean queueIdle();
}
同样分析 next 方法,可以看到一个 MessageQueue 最多设定 4 个 IdleHandler
// MessageQueue.java
Message next() {
// 若已经被depose mPtr就会被设定为0
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
// 下一个信息的时间
int nextPollTimeoutMillis = 0;
// 进入无限循环,也就是说next会导致block
for (;;) {
... 省略部分
synchronized (this) {
... 省略部分
// 检查是否有设置IdleHandler
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
// 最多设置4个Idle Handler
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// 循环
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
// 当没有信息时通知接口
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
// 返回 false 就移除
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
... 省略部分
}
}
Looper#
它是组成消息的重要关键(Handler、Message、MessageQueue),它的角色是驱动
名称 | 参数:回传 | 解释 |
---|---|---|
myLooper | void : Looper | 以当前线程为主,取得当前 Thread 的 Looper |
getMainLooper | void : Looper | 取得主线程的 Looper |
Looper - ThreadLocal#
最后 Looper 则是让整个 Hanler 机制循的动力,有 Looper 的推动 Handler 才能正常接收、发送信息
Looper 中包含了一个 MessageQueue(在构造函数中建构的)
// ava/android/os/Looper.java
public final class Looper {
// 私有函数
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
}
当你每创建一个线程就必须为这个线程准备 Looper,否则在 Handler 发送消息时就会 crush(上面有说到会检查),创建主要有以下步骤
Looper 准备工作(prepare 函数)
创建 Handler 发送&接收消息
Looper 开始运作(loop 函数)
class LooperThread extends Thread {
private Handler handler;
public void run() {
// 1
Looper.prepare();
// 2.
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//... 处理 Message
}
}
// 3.
Looper.loop();
}
}
ThreadLocal 这里大概提及,ThreadLocal 也就是线程隔离,使用线程 Thread 作为 Key 储存,而 Value 就是你要拷贝到每个线程的数据(每个子线程都持有一个数据)
//android/os/Looper.java
public final class Looper {
// 拷贝线程的数据是Looper
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) // 一个线程只能prepare一次
throw new RuntimeException("Only one Looper may be created per thread");
}
// 为当前Thread设定Looper
sThreadLocal.set(new Looper(quitAllowed));
}
}
当你建立一个 Handler 时,在 Handler construct 就会透过当前的线程取得 Looper
// Handler
public Handler(@Nullable Callback callback, boolean async) {
...
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;
}
// -----------------------------------------------------------------
// Looper
public static @Nullable Looper myLooper() {
// sThreadLocal是静态的,会透过当前Thread作为Key取得Looper
return sThreadLocal.get();
}
Looper & Handler#
Looper 跟 Handler 的关系可以从 new Handler()这个构造函数中看出,它是透过 myLooper 方法,透过目前的线程在 ThreadLocal 中取得该当前线程所拥有的 Looper
// Handler construct
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
... 忽略
// 取得当前线程的 Loop
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
//Looper...
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
Looper & UI Thread#
Android 中 Activity 的主线程是 ActivityThread’s main ()
public static void main(String[] args) {
...
Looper.prepareMainLooper(); //"1. "
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
//"2. "
sMainThreadHandler = thread.getHandler();
}
...
// End of event ActivityThreadMain.
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
主线程的 Looper 是不可以关闭的,并且使用类同步
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
// 属性...
private static Looper sMainLooper; // guarded by Looper.class
Looper#loop
,首先取得目前线程所拥有的 Looper,再取出 Looper 内部有的 MessageQueue,最后无限循环整个消息对列
// Looper.java
public static void loop() {
final Looper me = myLooper();
...
final MessageQueue queue = me.mQueue;
...
for (;;) {
//
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
try {
// 解决是谁再呼叫dispatchMessage,target为MessageQueue中的Handler
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...
msg.recycleUnchecked();
}
}
ThreadLocal#
ThreadLocal 的功能主要是做到线程隔离(用线程隔离数据),简单来说可以把 ThreadLocal 当作一个 Map(但实际来说它并不是 Map),它的 Key 是 Thread,Value 是一个泛型
// 前面Looper.prepare()内部就有使用到set()方法
public void set(T value) {
Thread t = Thread.currentThread(); //"1. "
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
// 前面Handler()构造函数内部就有使用到get()方法
public T get() {
Thread t = Thread.currentThread(); //"2. "
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
它使用目前呼叫它的 Thread.currentThread 作为 Key 存入,Value 是泛型
依照当前线程(currentThread),取的 Value