Android源码学习(1) 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。

消息处理

Handler通过dispatchMessage处理往其发送的消息:

public void dispatchMessage(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(Message msg) {
}

如果是Runnable,将直接执行;如果是普通的Message,将交由handlMessage进行处理。自定义Handler时,通过重写handlMessage进行具体处理。

posted on 2017-10-08 22:55  游不动の鱼  阅读(390)  评论(0编辑  收藏  举报