Android源码学习 Handler

Posted 荆棘鸟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android源码学习 Handler相关的知识,希望对你有一定的参考价值。

Handler的实例化

在安卓开发中,经常会用到Handler将任务提交到指定线程(例如主线程)去执行或者让其延迟执行。Handler的构造函数有多种重载形式,但最终都调用到如下两种之一:

public Handler(Callback callback, boolean async) {
    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;
}

public Handler(Looper looper, Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

可以看到:这两个构造函数的区别只是Looper的获取方式不一样,当未指定Looper时,Handler内部会通过Looper.myLooper()静态方法,获取当前线程的Looper。我们往Handler上发送的Message或者Runnable正是由这个Looper(或该Looper的线程)负责处理的。我们可以通过Looper.getMainLooper()获取主线程的Looper。

发送Message或者Runnable

调用post、postAtTime、postDelayed提交Runnable,调用sendMessage、sendEmptyMessage、sendMessageDelayed、sendEmptyMessageDelayed、sendMessageAtTime、sendEmptyMessageAtTime发送Message,最终都调用到sendMessageAtTime:

 1 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
 2     MessageQueue queue = mQueue;
 3     if (queue == null) {
 4         RuntimeException e = new RuntimeException(
 5                 this + " sendMessageAtTime() called with no mQueue");
 6         Log.w("Looper", e.getMessage(), e);
 7         return false;
 8     }
 9     return enqueueMessage(queue, msg, uptimeMillis);
10 }
11 
12 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
13     msg.target = this;
14     if (mAsynchronous) {
15         msg.setAsynchronous(true);
16     }
17     return queue.enqueueMessage(msg, uptimeMillis);
18 }

也就是说,提交的Runnable最终会被包装成Message,此时Message的callback字段将指向该Runnable。所有提交的Message都将会被插入名为mQueue的有序队列中,排序的依据便是传入的uptimeMillis(该值在enqueueMessage操作中会被赋给Message的when字段)。MessageQueue使用生产者-消费者模式,post*和send*产生的消息,最终会被Looper消费。(第2行中将mQueue赋给局部变量queue再通过改变访问mQueue,显然是出于多线程并发的安全性考虑)

使用postAtFrontOfQueue、sendMessageAtFrontOfQueue可以分别提交Runnable和Message到mQueue的队首,该Runnable或者Message将在Looper的下次循环中处得到处理。

使用removeCallbacks、removeMessages、removeCallbackAndMessages可以移除掉已经提交的Runnable或者Message。

以上是关于Android源码学习 Handler的主要内容,如果未能解决你的问题,请参考以下文章

Android源码学习 Handler

Android Handler消息机制02-Looper源码学习

Android源码学习-----Handler机制

Android Studio - 如何从片段中停止 handler.postDelayed?

Android Handler消息机制03-Message源码学习

Android Handler消息机制03-Message源码学习