看看Android Handler源码

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lvzhongdi/article/details/80913035

趁着有时间,看看Android源码,先来看看Handler,后期的时候在更新吧。都忘记了上次看源码是什么时候了。废话不哆嗦了,先了解下Handler是干嘛的,内容简介啊,原理啊,里面实现的方法啊,涉及到的设计模式啊,我进来满足大家,给大家展示,至于写个什么样的demo我还没想好,不过网上很多了,可以自己去寻找寻找。开始搞起~
加油干
一.Handler 讲什么的?
每个Handler实例都与一个线程和该线程的消息队列相关联。当您创建一个新的Handler时,它被绑定到创建它的线程/消息队列 ——从那开始,它将传递消息发送该消息队列中,并在消息队列结束时执行它们。
二.我们主要拿来干嘛呢?
两件事儿能干:
1.调度消息和代码,以便在将来的某个时间执行;
2.对要在不同于您自己的线程上执行的操作进行查询;
三.简单的画了一个图,理解一下Handler+Looper+Message+MessageQueue的工作原理
Handler工作原理简介

通俗来讲:
1.创建一个Handler,然后Handler发送一个消息(Message)放在消息队列(MessageQueue)中。
2.通过Looper的死循环,然后不断的从消息队列中去消息,然后处理消息。
3.处理完的消息,通过Handler的handlerMessage或者是CallBack方法来回调给Handler。
这样整个过程就完成了。

四. 我们看下Handler中提供的构造方法
1.public Handler()
默认构造函数将此处理程序与当前线程的Looper关联。如果该线程没有循环器,则此处理程序将无法接收消息,因此会引发异常。
2.public Handler(Callback callback)
构造函数将此处理程序与当前线程的队列关联,并接受一个可在其中处理消息的回调接口。
3.public Handler(Looper looper)
使用提供的队列而不是默认队列。
4.public Handler(Looper looper, Callback callback)
使用提供的队列而不是默认队列,并进行回调接口,在其中处理消息。
五.看看里面我们常用的几个方法的实现;
1.handler的sendMessage()

    /**
     * Pushes a message onto the end of the message queue after all pending messages
     * before the current time. It will be received in {@link #handleMessage},
     * in the thread attached to this handler.
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

sendMessage 里面实现的是一个sendMessageDelayed,那我们继续看看他的源码吧;

/**
     * Enqueue a message into the message queue after all pending messages
     * before (current time + delayMillis). You will receive it in
     * {@link #handleMessage}, in the thread attached to this handler.
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.  Note that a
     *         result of true does not mean the message will be processed -- if
     *         the looper is quit before the delivery time of the message
     *         occurs then the message will be dropped.
     */
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

其中的2个参数,一个是传递的消息Message、 另外的是我们要执行的延迟时间;按照源码中的提示,接着看看下面的sendMessageAtTime方法;

 public boolean sendMessageAtTime(Message msg, long uptimeMillis)
    {
        boolean sent = false;
        MessageQueue queue = mQueue;
        if (queue != null) {
            msg.target = this;
            sent = queue.enqueueMessage(msg, uptimeMillis);
        }
        else {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
        }
        return sent;
    }

啊哈,终于可以看到最终的实现了,简单的分析一下:
先看看我们创建的MessageQueue中是否有未处理的消息,之后要看的就是enqueueMessage方法的返回值来判断是否成功。看看这个方法搞什么呢?
在MessageQueue中的源码看到这个方法如下;

final boolean enqueueMessage(Message msg, long when) {
        if (msg.when != 0) {
            throw new AndroidRuntimeException(msg
                    + " This message is already in use.");
        }
        if (msg.target == null && !mQuitAllowed) {
            throw new RuntimeException("Main thread not allowed to quit");
        }
        synchronized (this) {
            if (mQuiting) {
                RuntimeException e = new RuntimeException(
                    msg.target + " sending message to a Handler on a dead thread");
                Log.w("MessageQueue", e.getMessage(), e);
                return false;
            } else if (msg.target == null) {
                mQuiting = true;
            }

            msg.when = when;
            //Log.d("MessageQueue", "Enqueing: " + msg);
            Message p = mMessages;
            if (p == null || when == 0 || when < p.when) {
                msg.next = p;
                mMessages = msg;
                this.notify();
            } else {
                Message prev = null;
                while (p != null && p.when <= when) {
                    prev = p;
                    p = p.next;
                }
                msg.next = prev.next;
                prev.next = msg;
                this.notify();
            }
        }
        return true;
    }

1.我们来看下if里面的条件,如果mMessages对象为空,或者when为0也就是立刻执行,或者新消息的when时间比mMessages队列的when时间还要早,符合以上一个条件就把新的msg插到mMessages的前面 并把next指向它,也就是msg会插进上图中队列的最前面,等待loop的轮询。
2.如果上面的条件都不符合就进入else代码中,我们可以看到17行是有个for的死循环遍历已有的message对象,其中第20行中有个if语句when < p.when when是新消息的执行时间,p.when的是队列中message消息的执行时间,如果找到比新的message还要晚执行的消息,就执行 msg.next = p; prev.next = msg; 也就是把插到该消息的前面,优先执行新的消息。
其实Handler总结到这里,我也不知道该说什么了,简单的分享一个demo,大家都会的,也让大家理解一下Handler的应用吧,实现一个倒计时功能;哈哈哈
eg:
在MainActivity中创建一个Handler,然后实现倒计时。代码如下:

 private static int TIME = 5;
    private TextView mTime;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    TIME--;
                    mTime.setText(TIME + "s");
                    if (TIME > 0) {
                        Message message = handler.obtainMessage(1);
                        handler.sendMessageDelayed(message, 1000); 
                    } 
            }
            super.handleMessage(msg);
        }
    };

学习的时光总是要花费的,希望大家喜欢我的分享;我的公众号也可以关注哦。扫码下面的二维码即可;
这里写图片描述

猜你喜欢

转载自blog.csdn.net/lvzhongdi/article/details/80913035