Handler运行机制

handler的使用机制在面试的时候经常会被问到,最近把handler相关的源码看了一下,所以今天就把handler的源码梳理了一下,由于本人才疏学浅,哪里分析的不够透测,不够准确的希望拍砖指正

Handler可以用来解决子线程和UI线程上通信的问题

Handler在运行的时候主要涉及到的类有Looper,Handler,MessageQueue,Message,先来大概的概括一下这几个类分别做了哪些事情,Looper负责从MessageQueue里边读取Mesage,读取到Message之后掉msg.target.dispatchMessage去处理,最后会掉到handleMessage (msg),Handler负责发送Message到MessageQueue里边,MessageQueue用来存放Message的,Message里边存放一些数据,比如what,arg1,arge2,obj,target(这个是Handler),next(这个是一个Messag)

下面针对这几个类结合代码分别进行讲解

一、Looper

1、在主线程中使用handler时,不需要手动对Looper做任何掉用,这是为什么呢?因为在主线程当中系统已经帮我掉用好啦,这个想了解的同学可以到ActivityThread这个类里边去看 main函数,这里就不贴ActivityThread相关的代码了,系统调用的是Looper里的prepareMainLooper()。看代码:

 /**
     * Initialize the current thread as a looper, marking it as an
     * application's main looper. The main looper for your application
     * is created by the Android environment, so you should never need
     * to call this function yourself.  See also: {@link #prepare()}
     */
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

重点看注释。同时looper负责从MessageQueue里边读取Message的这个循环loop()放在也在这里进行了掉用

2、在子线程中使用handler的时候要手动去掉用Looper.prepare(),否则会报错,一个线程和一个looper,一个MessageQueue关联。无论是主线程还是子线程生成的looper对象都放到了LocalThread<T>里边,在new出来handler对象之后在手动的掉用looper.loop()。

3、looper是如何取到消息的?loop方法里有个死循环,不断的读取MessageQueue里边的Message,当读取到的Message为null时,则return,退出循环,退出循环之后当handler再次发送Message的时候是怎么开始激发looper再次去读取消息的呢?留个悬念,这个代码在MessageQueue的里边,一会再说,哈哈。

二、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;
    }

1、当new Handler对象的时候,无论传不传参,传一个参数,传两个参数等,最终都会执行这个代码片段,现在就来分析一下这段代码,这里获取到了mLooper,mQueue,mLooper是通过Looper.prepare 或者Looper.prepareMainLooper()生成的,mQueue的初始化也是Looper里边初始化的,到这里Looper,Handler,MessageQueue,已经关联上了。

2、接下来说一下,handler发送消息,以sendMesage(Message msg)为例,掉用流程看图

在enqueueMessage里边掉用了queue.enqueueMessage(msg, uptimeMills);将消息放到MessageQueue里

三、MessageQueue

先说一下一里的3,退出循环之后当handler再次发送Message的时候是怎么开始激发looper再次去读取消息的,这个是在 MessageQueue的enqueueMessage这个方法里边触发的,当有消息发过来了把needWake置为true,然后掉用了一个native的方法nativeWake。

下面看代码

boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }

        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

这块处理了消息的存放顺序,按时间的正序排列。

四、Message

是handler发送与接收处理的消息对象,这个是当handler发送消息的把Message这个对象传到Handler里边的,然后在有传到MessageQueue里边,当looper从MessageQueue里边读取到Message的时候最后返回到handleMessage(Message msg)这里的。

由于需要传递Object,Message实现了Parcelable接口,

到这里就都分析完了,再次强调说的不好或者说的不准确的地方欢迎指正哦。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值