handler基本原理

来源:互联网 发布:微商作图软件 编辑:程序博客网 时间:2024/06/05 21:56

handler的设计是android系统消息机制的体现,我们将耗时的任务通过子线程执行,而通过handler去切换到主线程去更新ui,因为android系统是不允许在其他线程更新ui的。其实消息机制的整个体系有三个类handler,MessageQueue,Looper。

每一个线程要想创建一个属于自己的handler,那么必须依赖一个looper和一个MessageQueue,当我们在主线程创建handler的时候是不需要手动的创建Looper的,因为系统已经为主线程创建好了,但是我们为其他的线程中创建handler的时候就必须手动的创建一个Looper了,现在looper创建好了,那么MessageQueue呢?不要担心,这个类在我们实例化Looper的时候在looper的构造方法中创建好了:

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

当然这个构造方法是私有的,它是在prepare中调用的。

loop的主要工作机制:

Looper的loop()方法是一个死循环,它会不停的从消息队列中取数据:

 public static void loop() { //代码已经过简化        final MessageQueue queue = me.mQueue;        for (;;) {              Message msg = queue.next(); // 取出消息            msg.target.dispatchMessage(msg); //发送给handler        }

loop()方法中通过MessageQueue的next()方法取数据,然后将取出的消息发送给handler.

MessagQueue的主要工作机制:

MessageQueue这个类维护着一个单链表实现的消息队列。里面有两个方法:

 boolean enqueueMessage(Message msg, long when){}//代码已经简化
 Message next() {}//代码已简化

enqueueMessage()这个方法是将消息入队,在handler源码中如下方法调用:

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

next()方法是从消息队列中取出消息,在取出的同时将消息删除,next方法是在looper中调用,上面代码已经贴出。

handler中主要通过dispatchMessage()这个方法接收消息,在这个方法中首先判断msg.callback是否为空,这个不为空那么消息就是通过handler.post系列方法发送的runnable对象,否则就是Message对象,那就调用我们在实现hanlder中传人的接口回调方法中,如果这个接口为null,那么就调用handler的handleMessage()方法,这个方法什么都没做,如果通过继承handler实现一个子类,那么需要复写这个方法。

/**     * Handle system messages here.     */    public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }

以上就是三者的基本工作机制。

最后介绍一个类是ThreadLocal,这个类应用在了Looper的实现中,我们之所以在每个线程中创建各自的Looper而不会混淆,每个handler都对应自己的Looper,这里面ThreadLocal是立了大功劳的,这个类可以理解成线程中的局部变量,为每个线程保存它们自己的数据,它就是有这个特性,原理就是这个类提供的set,get方法,set是用于设置这个线程的专有数据,get是用来获取这个线程的专有数据,在设置和获取的方法里,都会取到这个线程的专有数组,存储在这个数组中。所以每个线程都可以有自己的Looper.

原创粉丝点击