Android Handler机制——Handler
Handler机制是一个典型的异步环境下的生产者-消费者模型,Handler为生产者,Looper为消费者,Message为产物,MessageQueue则是暂存产物的仓库(缓冲区)。
一、构造
public Handler();
public Handler(@Nullable Callback callback);
public Handler(@NonNull Looper looper);
public Handler(@NonNull Looper looper, @Nullable Callback callback);
public Handler(boolean async);
public Handler(@Nullable Callback callback, boolean async);
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async);
Handler有多个构造函数,但实际初始化都是在最后两个构造中实现。
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;
final boolean mAsynchronous;
public Handler(@Nullable Callback callback, boolean async) {
//用于检测检测匿名、本地或成员类扩展这个 Handler 类并且不是静态的。 这类类可能会造成泄漏。
//一般不启用
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;
}
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
可见Handler的构造函数只做一件事——对mLooper、mQueue、mCallbac、mAsynchronous四个成员变量赋值。
这两个构造函数的主要区别便是获取mLooper的手段不同。若构造传参没有传入looper,则mLooper通过Looper.myLooper()方法获取Looper,该方法会获取当前运行线程的Looper。mQueue则是从Looper中获取的MessageQueue,MessageQueue由Looper负责实例化。
类关系如下图所示。
二、事件投递
Handler作为异步处理机制。MessageQueue为装载事件(消息)的容器,Looper为的线程驱动主体。Handler直译为处理器,实际只是整个机制向外暴露的接口。它有多个接口可以实现事件的投递。
public final boolean post(@NonNull Runnable r);
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis);
public final boolean postAtTime(@NonNull Runnable r, @Nullable Object token, long uptimeMillis);
public final boolean postDelayed(@NonNull Runnable r, long delayMillis);
public final boolean postDelayed(Runnable r, int what, long delayMillis);
public final boolean postDelayed(@NonNull Runnable r, @Nullable Object token, long delayMillis);
public final boolean postAtFrontOfQueue(@NonNull Runnable r);
public final boolean sendMessage(@NonNull Message msg);
public final boolean sendEmptyMessage(int what);
public final boolean sendEmptyMessageDelayed(int what, long delayMillis);
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis);
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis);
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis);
public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg);
public final boolean executeOrSendMessage(@NonNull Message msg);
暴露出来的接口很多,但最终都会调用到sendMessageAtTime或者sendMessageAtFrontOfQueue,而这两个方法最终会调到enqueueMessage方法中。
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, 0);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
//Message绑定Handler
msg.target = this;
//该变量在Handler机制跨进程使用时用到,该功能未对APP端开放
msg.workSourceUid = ThreadLocalWorkSource.getUid();
//根据mAsynchronous判断是否同步执行
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
sendMessageAtTime和sendMessageAtFrontOfQueue唯一区别便是时间参数。MessageQueue中维护了一个链表用于存储Message,该链表会根据enqueueMessage方法中传入的时间对Message进行排序,时间小的先处理。sendMessageAtFrontOfQueue顾名思义,其传入时间为0,进入MessageQueue后必然会排在最前面,会最优先处理对应的Message。
enqueueMessage主要职责便是将Message塞入MessageQueue中。值得注意的是,Message会在该方法中与Handler绑定。而msg.workSourceUid用于存储Message发送方的Uid,这个变量会在Handler用于跨进程通信时用到,但APP端并没有暴露Handler跨进程相关的功能,因此并不需要过多关注它。
三、事件处理器
Handler机制有多个事件处理方式。
1.重载Handler的handleMessage方法。
2.传入Message时设置Message的callback成员变量。
3.设置Handler的mCallback成员变量。
从Handler处理事件的方法来看:
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
public void handleMessage(@NonNull Message msg) {
}
在looper处理事件时,便会调用dispatchMessage方法。从代码可以看出,三种方式的优先级分别是:1.message的callback。2.Handler的mCallback成员变量以及handleMessage方法。
值得注意的是,当message有callback成员变量是便不会执行后续的处理方法,且当mCallback的返回值未true时,也不会再执行Handler的handleMessage方法。