Handler是Android中提供的一种异步回调机制,也可以理解为线程间的消息机制。为了避免ANR,我们通常会把一些耗时操作(比如:网络请求、I/O操作、复杂计算等)放到子线程中去执行,而当子线程需要修改UI时则子线程需要通知主线程去完成修改UI的操作,则此时就需要我们使用Handler机制来完成子线程与主线程之间的通信。
尽管Message的构造器是公开的,但是获取Message对象的最好方法是调用Message.obtain()或者Handler.obtainMessage(), 这样是从一个可回收对象池中获取Message对象。
这两种方式都比直接new一个Message对象在性能上更优越.
Handler mHandler = new Handler();
- @Deprecated
- public Handler() {
- this(null, false);
- }
获取当前Handler实例所在线程的Looper对象:mLooper = Looper.myLooper()
如果Looper不为空,则获取Looper的消息队列,赋值给Handler的成员变量mQueue:mQueue = mLooper.mQueue
可以设置Callback 来处理消息回调:mCallback = callback
Handler是消息的处理者,但是它并不是最终处理消息的那个大佬,它有且只能有一个上级领导,就是Looper,Handler是将消息上报给Looper(领导),然后排队等待,等Looper(领导)处理完消息了,就会通知Handler去领取消息,给Handler分配任务,Handler拿到消息后在自行往下分发,Handler只能听命与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;//获取MessageQuene
- mCallback = callback;
- mAsynchronous = async;
- }
- Handler mHandler = new Handler(){
- @Override
- public void handleMessage(@NonNull Message msg) {
- super.handleMessage(msg);
- }
- };
1、拿到mHandler所在线程的Looper,当前mHandler是在Activity中创建的,很明显,当前的线程就是主线程,所以 mHandler的成员变量mLooper = Looper.myLooper(),此处就已经将当前的主线程Looper赋值过去了。
2、紧接着,判断mLooper 是否为空,明显不为空,所以又会将主线程的消息队列赋值给mQueue。告诉Handler,你要是有消息,就送到这个消息队列中来,我(Looper)会一个个按顺序处理,处理完后我就会告诉你,你再处理。
Handler只能绑定一个线程的Looper;
Handler的消息是发送给Looper的消息队列MessageQueue,需要排队处理;

- public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
- MessageQueue queue = mQueue;//获得当前的消息队列
- if (queue == null) { //若是在创建Handler时没有指定Looper,就不会有对应的消息队列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);
- }
- private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
- long uptimeMillis) {
- msg.target = this;
- msg.workSourceUid = ThreadLocalWorkSource.getUid();
-
- if (mAsynchronous) {
- msg.setAsynchronous(true);
- }
- return queue.enqueueMessage(msg, uptimeMillis);
- }
msg.target = this
在发送消息到消息队列之前,明确的指定了消息的target为当前的Handler,以便于在后面Looper分发消息时用到。
queue.enqueueMessage(msg, uptimeMillis)
然后调用了消息队列的enqueueMessage()方法,并传递了两个参数,一个Message,一个是long型的时间。
消息发送后,交给Looper等待处理,处理完后会重新通知Handler处理,那么,是怎样通知Handler处理消息的呢?秘密就在dispatchMessage()这个方法中
- public void dispatchMessage(@NonNull Message msg) {
- if (msg.callback != null) {
- handleCallback(msg);
- } else {
- if (mCallback != null) {
- if (mCallback.handleMessage(msg)) {
- return;
- }
- }
- handleMessage(msg);
- }
- }

当Looper处理完Message后,会使用到Message的target,即上面说到的target,即发送消息的那个Handler,Looper会调用Handler的dispatchMessage()方法分发消息,所以前面在enqueueMessage()发送消息的时候,为什么非得指明Message的target就是这个道理。
回到dispatchMessage()这个方法:
1、首先会判断Message的callback是否为空,此处的callback就是前面我们在Message中说到的,在静态方法创建Message时,可以指定的callback,若不为空,则将结果回调到callback中;
2、若Handler的mCallback 不为空,也一样的道理。
3、平时我们都没有传入这个callback,而是直接实现handleMessage()这个方法,在这个方法中处理更新UI任务。
以上就是Handler发送和接收消息的基本过程:把消息发送到队列—>然后等待—>接收消息—>分发消息—>在回调中处理。
Handler发送消息会调用MessageQueue的enqueueMessage()方法
- boolean enqueueMessage(Message msg, long when) {
- if (msg.target == null) { //判断msg的所属Handler
- throw new IllegalArgumentException("Message must have a target.");
- }
-
- synchronized (this) {//因为是队列,有先后之分,所以用了同步机制
- if (msg.isInUse()) {
- throw new IllegalStateException(msg + " This message is already in use.");
- }
-
- if (mQuitting) {
- 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;
- //若队列为空,或者等待时间为0,或者比前面那位的等待时间要短,就插队
- if (p == null || when == 0 || when < p.when) {
- // New head, wake up the event queue if blocked.
- msg.next = p;
- mMessages = msg;
- needWake = mBlocked;
- } else {
- // Inserted within the middle of the queue. Usually we don't have to wake
- // up the event queue unless there is a barrier at the head of the queue
- // and the message is the earliest asynchronous message in the queue.
- needWake = mBlocked && p.target == null && msg.isAsynchronous();
- Message prev;
- //此处for循环是为了取出一个空的或者when比当前Message长的一个消息,然后进行插入
- for (;;) {
- prev = p;
- p = p.next;
- if (p == null || when < p.when) {
- break;
- }
- if (needWake && p.isAsynchronous()) {
- needWake = false;
- }
- }
- msg.next = p; // invariant: p == prev.next
- prev.next = msg;
- }
-
- // We can assume mPtr != 0 because mQuitting is false.
- if (needWake) {
- nativeWake(mPtr);
- }
- }
- return true;
- }
以上就是消息队列插入消息的过程原理,通过单向链表的数据结构来存储消息。既然有了插入消息的方法供Handler插入消息,那么应该有对应的取出消息的方法,供Looper调用取出消息处理,它就是Message.next这个变量(结点)
Looper在Handler机制中扮演着关键的一环,他是循环处理消息的发动机,永不停息(永动鸡),它不断的从消息队列中取出的消息,处理,然后分发处理事件。每个线程都可以且只能绑定一个Looper。主线程之所以能处理消息,也是因为在APP启动时,在ActivityThread中的main()方法中就已经启动了Looper循环。
- 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.");
- }
- if (me.mInLoop) {
- Slog.w(TAG, "Loop again would have the queued messages be executed"
- + " before this one completed.");
- }
-
- me.mInLoop = true;
-
- // Make sure the identity of this thread is that of the local process,
- // and keep track of what that identity token actually is.
- Binder.clearCallingIdentity();
- final long ident = Binder.clearCallingIdentity();
-
- // Allow overriding a threshold with a system prop. e.g.
- // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
- final int thresholdOverride =
- SystemProperties.getInt("log.looper."
- + Process.myUid() + "."
- + Thread.currentThread().getName()
- + ".slow", 0);
-
- me.mSlowDeliveryDetected = false;
-
- for (;;) {
- if (!loopOnce(me, ident, thresholdOverride)) {
- return;
- }
- }
- }
- private static boolean loopOnce(final Looper me,
- final long ident, final int thresholdOverride) {
- Message msg = me.mQueue.next(); // might block //取出队头的消息
- if (msg == null) {
- // 如果消息为空,则跳过,继续执行下一个message
- // No message indicates that the message queue is quitting.
- return false;
- }
-
- // This must be in a local variable, in case a UI event sets the logger
- final Printer logging = me.mLogging;
- if (logging != null) {
- logging.println(">>>>> Dispatching to " + msg.target + " "
- + msg.callback + ": " + msg.what);
- }
- // Make sure the observer won't change while processing a transaction.
- final Observer observer = sObserver;
-
- 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 (me.mSlowDeliveryDetected) {
- if ((dispatchStart - msg.when) <= 10) {
- Slog.w(TAG, "Drained");
- me.mSlowDeliveryDetected = false;
- }
- } else {
- if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
- msg)) {
- // Once we write a slow delivery log, suppress until the queue drains.
- me.mSlowDeliveryDetected = true;
- }
- }
- }
- if (logSlowDispatch) {
- showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
- }
-
- if (logging != null) {
- logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
- }
-
- // Make sure that during the course of dispatching the
- // identity of the thread wasn't corrupted.
- 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();
-
- return true;
- }
Looper的处理消息的循环还是挺简单的,就是拿出消息,然后分发,然后回收