Android线程间异步通信机制源码分析(2)

public Handler(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 that has not called Looper.prepare()");
        }
      mQueue = mLooper.mQueue;// 获取到looper管理的消息队列
        mCallback = callback;// 自定义的回调函数
        mAsynchronous = async;
    }

其中有关内存泄露问题我们稍后再谈。先关注一下我们的handler在创建时做了哪些工作。在谈论整个通信机制的时候我们说过,一个线程只能有一个looper用来轮询唯一的一个消息队列,即线程,looper,消息的队列的关系是一一对应的。而handler和looper之间是一对多的关系,即一个looper可以由多个handler来为它服务。在handler的构造函数中,主要工作就是把handler和它要服务的looper,消息队列关联起来。

handler可以向队列中发送消息或者添加一个可执行的runnable对象,消息队列会安排在某一时刻进行消息处理或者执行runnable对象run方法:
•post(Runnable r):将runnable对象加入消息队列,该runnable对象将会被消息队列所在线程执行。
•postAtTime(Runnable, long): 将runnable对象加入消息队列,在指定的时间执行该runnable对象。
•postDelayed(Runnable r, long delayMillis):将runnable对象加入消息队列,经过指定延迟时间后执行。
•sendEmptyMessage(int what):将一条仅包含what值的消息发送给消息队列
•sendMessage(Message msg):将一条消息加入消息队列
•sendMessageAtTime(Message msg, long uptimeMillis):在指定时间将一条消息加入队列尾部
•sendMessageDelayed(Message msg, long delayMillis): 在经过指定时间延迟后,将一条消息加入队列尾部


        通过这些方法,handler将message对象交给了消息队列messageQueue。looper从消息队列中取出message后,会调用message所持有的handlerdispatch方法,分发给handler来处理该消息:

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {// 如果message对象持有回调对象,则执行它
            handleCallback(msg);
        } else {
            if (mCallback != null) {// 如果当前handler持有消息处理的回调函数,则执行它
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);// 如果都没有,则执行用户自定义的消息处理方法
        }
    }

管家Looper和信箱MessageQueue

从上面的分析我们可以了解,message对象是通过handler间接的加入到消息队列中的,然后消息队列将message对象组织成一个队列提供给looper分发。如果只看名字,我们会猜想这个类中使用队列这种数据结构来组织message,然而并不是这样的。MessageQueue将message对象按时间顺序组织成一个链表的形式来管理。

在创建handler对象的时候,我们通过looper.myLooper方法从threadLocal中获取到与当前线程一一对应的looper对象。那么当前线程是何时创建了整个looper对象并将其放入threadLocal呢?在Android的UI线程中,早已自动替我们创建好了looper;而如果是我们自己创建的线程,那么就需要调用prepare方法来创建出looper对象:

public static void prepare() {
        prepare(true);
    }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/70ed5be6de341d62346977b4a5e06e88.html