码迷,mamicode.com
首页 > 移动开发 > 详细

Android源码学习(1) Handler

时间:2017-10-09 00:24:04      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:hat   empty   操作   targe   android源码   can   消费者模式   get   llb   

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

标签:hat   empty   操作   targe   android源码   can   消费者模式   get   llb   

原文地址:http://www.cnblogs.com/moderate-fish/p/7618330.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!