作为一个Android开发人员,或者对Android由一定了解的人员,我想你对于Handler并不陌生,作为Android中最基础的组件之一,几乎所有的Android面试都会有关于Handler消息机制的题目,所以对于作为Android开发人员的我们,有什么理由不去了解Android的底层原理呢?
在Android的Handler消息机制中,主要有Handler,Message、MessageQueue、Looper
Handler
在Handler消息几种中,Handler类的作用主要是负责发送消息和最终对消息的处理,Handler的构造方法有六个构造方法,有三个参数,这三个参数为(@NonNull Looper looper, @NonNull Callback callback, boolean async),由注解可知looper和callback传入是不能为空,而当不传入looper对象时,构造方法也会去通过Looper静态方法获取looper对象,而当获取的looper对象为空时,程序会抛出异常,提示必须先调用Looper.prepare()方法,Looper.prepare()方法会创建一个looper对象,然后和当前线程绑定,具体如何实现请看Looper部分讲解。callback参数则是handler事件处理回调函数,传入这个参数后就可以不用实现handler子类来处理回调事件了。async参数为true则表示当前handler对象是否为异步handler,客户端一般不使用handler发送异步消息,所以一般来说我们都不使用带这个参数的构造方法,而且带有该参数的构造方法都是@hide方法,所以需要创建异步handler需要通过Handler的静态方法createAsync。至于同步消息和异步消息有什么区别,请看Looper部分
public Handler(@Nullable 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();//获取looper对象
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;
}
Handler通过postXX或者sendXX发送消息,源码如下
public final boolean post(@NonNull Runnable r) {//任务调度
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {//定时执行任务
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(//带有验证信息的定时任务
@NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {//延时任务调度
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean postDelayed(Runnable r, int what, long delayMillis) {//带有额外信息what的延时任务调度
return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);
}
public final boolean postDelayed(//带有验证信息的延时任务调度
@NonNull Runnable r, @Nullable Object token, long delayMillis) {
return sendMessageDelayed(getPostMessage(r, token), delayMillis);
}
public final boolean postAtFrontOfQueue(@NonNull Runnable r) {//优先执行的任务调度
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
public final boolean sendMessage(@NonNull Message msg) {//发送一个msg信息
return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what) {//发送一个空的msg信息
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {//发送一个空的且延时的msg信息
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {//发送一个空的且定时的msg信息
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {//发送一个延时的msg信息
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {//发送一个定时的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, uptimeMillis);//消息入队
}
public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
MessageQueue queue = mQueue;
if (queue == null) {//消息队列为空时抛出异常,在Looper.prepare()中创建,创建looper对象后就不会为空
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, 0);
}
public final boolean executeOrSendMessage(@NonNull Message msg) {
if (mLooper == Looper.myLooper()) {//如果时同一线程,则直接执行,否则入队
dispatchMessage(msg);
return true;
}
return sendMessage(msg);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {//如果时异步消息,则先标记message为异步消息
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);//通过消息队列进行入队
}
通过上面方法我们可以知道无论通过sendXX发送消息还是通过postXX调度任务,最终都需要通过MessageQueue的enqueueMessage方法进入队列,不同之处仅在于任务内容和处理任务时间不同,以及是否为异步消息。最后通过Looper进行消息队列的处理,最后通过handler的dispatchMessage方法经行分发,分发代码如下
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {//callback对象为Runnable,不为空的是直接运行runnable方法
handleCallback(msg);
} else {
if (mCallback != null) {//mCallback是构造handler时传入的callback,不为空的话通过它分发消息
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);//msg和handler的callback都为空时需要,创建handler时需要实现该方法进行任务的分发处理
}
}
此外Messenger主要通过Handler的getIMessenger方法来实现进程间的通信
Looper
在一个线程中需要使用handler消息机制需要先通过Looper.prepare()创建looper对象,而且有源码可知,prepare方法只能被一个线程调用一次,looper对象通过静态常量对象sThreadLocal和线程进行绑定,从而确保了每个线程都只有一个looper对象。
public static void prepare() {
prepare(true);
}
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));
}
looper核心的方法是loop方法,loop方法里面是一个是循环,在这个死循环里主要负责维护MessageQueue队列的出队并且保证线程持续的运行,然后对出队消息进行分发。
在面试过程中往往会遇到这么一个问题,为什么loop方法不会导致ANR呢?解决这个额问题我们先得清楚ANR出现的条件,第一种情况是在Service的生命周期和BroadcastReceiver的onReceiver方法中执行耗时操作;第二种是在输入事件在5s内没有完成且有下一个事件等待处理的情况下。而loop的死循环会及时把收到的消息分发个各个handler对象处理,所以ANR和死循环并没有直接关系,而ANR只是主线程维护的死循环中一部分代码执行超时的结果。如果没有了loop的死循环,主线程也会因为线程的方法执行结束而被系统结束生命周期,进而结束整个进程。
public static void loop() {
final Looper me = myLooper();//获取当前线程的looper对象
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;//获取消息队列
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
final int thresholdOverride =
SystemProperties.getInt("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
+ ".slow", 0);
boolean slowDeliveryDetected = false;
for (;;) {
Message msg = queue.next(); //获取下一个待处理的消息,如果没有消息,线程会阻塞在这里
if (msg == null) {//如果消息为空的会推出循环,可通过quit和quitSafely方法清空消息队列
return;
}
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final Observer observer = sObserver;//消息队列处理监听器,设置接口为hide接口
final long traceTag = me.mTraceTag;
long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
if (thresholdOverride > 0) {
slowDispatchThresholdMs = thresholdOverride;
slowDeliveryThresholdMs = thresholdOverride;
}
final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);
final boolean needStartTime = logSlowDelivery || logSlowDispatch;
final boolean needEndTime = logSlowDispatch;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
final long dispatchEnd;
Object token = null;
if (observer != null) {
token = observer.messageDispatchStarting();
}
long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
try {
msg.target.dispatchMessage(msg);//消息分发
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (logSlowDelivery) {
if (slowDeliveryDetected) {
if ((dispatchStart - msg.when) <= 10) {
Slog.w(TAG, "Drained");
slowDeliveryDetected = false;
}
} else {
if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
msg)) {
slowDeliveryDetected = true;
}
}
}
if (logSlowDispatch) {
showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();//回收msg资源,并根据使用情况存入到sPool
}
}
loop方法中除了读messageQueue队列之外还做了一些日志,监听器,以及多进程通信的一些处理,但是主要逻辑还是消息的读取和分发
Message
Message是MessageQueue的节点对象,不仅封装what、arg1、arg2、obj及data等数据对象,还封装了next节点对象,所以MessageQueue队列是链表的数据结构,它还实现了Parcelable序列化,在进程Messager进程通信时也是通过其实现数据的传递。此外message还采用了GOF设计模式中的享元模式,我们可以通过Message的obtain方法创建message对象,这样可以减少对象的创建而达到内存优化的效果,Handler对象中的obtainMessage也是调用了Message中的obtain方法。
MessageQueue
上面我们已经提到过了,handler的sendXX或者postXX方法最终都会调用handler的enqueueMessage方法,而其最终调用的也是messageQueue的enqueueMessage方法。此方法会将msg消息按照when的先后顺序入队
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {//表示此消息正在使用
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {//调用quit方法后,不在处理任何消息
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null//第一次发送handler消息前为空
|| when == 0//通过handler的sendMessageAtFrontOfQueue方法发送时when为0
|| when < p.when) {//消息的处理时间小于当前处理的消息时间时直接将msg
msg.next = p;
mMessages = msg;
needWake = mBlocked;//mIdleHandlers没有元素时为true
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();//如果插入一个屏障消息
Message prev;
for (;;) {//遍历队列中的节点信息,并根据设定的when的大小将msg插入到合适的位置
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p;
prev.next = msg;
}
if (needWake) {
nativeWake(mPtr);//在没有消息的时候线程会通过nativePollOnce方法进行休眠
//此方法可以唤醒线程休眠状态
}
}
return true;
}
消息出队
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1;
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);//在没有消息的时候会阻塞,当有消息时会被及时唤醒
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {//如果当前消息是一个屏障消息,则优先处理异步消息,没有异步效益时,msg被赋值为null
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {//如果是一条延时消息,则计算延时时长
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {//移除当前节点
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
nextPollTimeoutMillis = -1;
}
if (mQuitting) {
dispose();
return null;
}
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
mBlocked = true;
continue;
}
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;
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
pendingIdleHandlerCount = 0;
nextPollTimeoutMillis = 0;
}
}