Android Handler机制

Handler主要作用:

1、             向线程的消息队列MessageQueue中添加Message;

2、             处理Message消息。

为了实现上面两个操作过程,面临两个问题:Handler如何向线程的MessageQueue添加Message?线程取出消息怎么能够调用到Handler的消息处理?

针对第一个问题,Handler如何向MessageQueue添加Message,查看Handler源码可以看到Handler具有MessageQueue类型变量mQueue。

    final MessageQueue mQueue;
    final Looper mLooper;
    final Callback mCallback;
    final boolean mAsynchronous;
    IMessenger mMessenger;

然后分析一下mQueue是如何赋值的,mQueue是final类型,Handler初始化时刻就需要赋值,查看Handler构造函数:

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();
        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;
    }


从构造函数中可知Handler的mQueue是Looper的成员变量mQueue赋值,我们看一下Looper的源码。

public final class Looper {
    private static final String TAG = "Looper";


    // sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class


    final MessageQueue mQueue;
    final Thread mThread;

... ...

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

}

从代码中可以看到mQueue是Looper的final成员变量,在构造的时候就会new 出一个MessageQueue对象。那么Handler的mLooper是如何赋值的?我们从Handler的构造函数中可以看到,mLooper有两种获取方式,一种是Looper.myLooper(),另一种是外部赋值。我们看一下Looper.myLooper()函数实现。

public static Looper myLooper() {
        return sThreadLocal.get();
    }

myLooper()是一个静态函数,从sTheadLocal中获取,sTheadLocal定义如下:

static final ThreadLocal<Looper> sThreadLocal= new ThreadLocal<Looper>();

sTheadLocal是一个静态ThreadLocal对象,ThreadLocal是怎么保存Looper对象?下面我们看一下ThreadLocal的实现。

public class ThreadLocal<T>

{

 	Values initializeValues(Thread current) {
    		return current.localValues = new Values();
	}
 
 
 
    	Values values(Thread current) {
          return current.localValues;
   	}

 




    static class Values

             {

           private Object[] table;

                            …

}

}

从上面实现我们可以看到ThreadLocal.Values是与线程相关的,存储的是线程的本地变量。根据ThreadLocal的get函数实现可知:首先获取当前Thread对象的保存的Values类型变量localValues如果localValues为空会调用initializeValues函数为当前线程创建一个Values对象;然后从localValues中获取Looper对象。如果是非UI线程,没有调用Looper.prepare(),获取的Looper对象为空。Looper的prepare函数会new一个Looper对象放入当前线程对应的ThreadLocal.Values中。三者关系如下图


总结以上分析得出结论:

(1)使用Handler必须依赖一个Looper;

(2)Handler发送Message实际是添加到Looper的MessageQueue中;

(3)非UI线程默认是没有Looper和MessageQueue,需要调用prepare()函数;

  

回到开始提出的问题,Handler如何向MessageQueue添加Message,现在我们知道了MessageQueue的由来,下面看一下Handler添加Message过程。

public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

我们可以向Handler传递一个Runnable对象,或者一个Message对象。当传递Runnable对象时,会把Runnable填充到一个Message对象中。

private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

sendMessageDelayed函数最终会调用到enqueueMessage函数。

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

这时会就把Message添加到了MessageQueue中。在enqueueMessage函数中会使用设置当前Message的target为当前的Handler对象。这时就完成了Handler的Message发送。

第二个问题:线程取出消息怎么能够调用到Handler的消息处理?

下面我们看一下Message类实现,Message对象包括两个重要成员变量,如下:

Handler target;
Runnable callback;


每个Message对象都会携带者Handler信息,这个Handler有什么作用呢?我们看一下Looper取出Message的处理过程。


Looper从MessageQueue中取出一个Message,然后调用msg的Handler对象target的dispatchMessage函数处理消息。


首先会判断msg是否有Runnable对象(msg.callback是否为空),例如前面介绍使用Handler的post一个Runnable对象时会把Runnable转为一个Message对象, Runnable对象同时赋值给Message的callback。如果msg.callback为空时会判断Handler是否设置了Callback,如果mCallback为空就会调用到handlerMessage。

Handler的消息发送和处理过程图如下:


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值