Handler源码窥探。

这里总结一下刷新UI的方法:

Handler.post(Runnable)
Handler.sendMessage()
View.post(Runnable)
AsyncTask
Activity.runOnUiThread()

看似上面有五种其底层都是通过Handler的消息队列的形式来实现的,从源码ActivityThread中,我们知道甚至从安卓中任何主线程事件的响应都是通过handler来实现,所以这里很有必要研究一下handler的源码了。=_=

话不多说直接上图:

这里写图片描述

了解Handler的机制设计到了下面几个类:
Handler,Message,MessageQueue,Looper,ActivityThread

这里我们首先从Handler的构造方法来看:
主要做了两件事情:
1、 通过Looper.myLooper拿到Looper对象;
2、 从Looper中将MessageQueue对象取出来,并赋值给Handler里面的mQueue

对于第一件事情:
1、我们查看Looper的源码:myLooper的实际上拿到的是ActivityThread创建的Looper;由于ThreadLocal是与线程绑定,所以,如果我们在主线程中任何地方创建的Handler都是拿到的是ActivityThread创建的Looper;(如果我们在子线程中创建,则直接回报没有找到Looper对象;),还有一点就是我们在Looper的构造方法里面发现了,在这里创建一个了一个MessageQueue;
简单来说:
安卓在启动的过程中,就创建了一个在主线程中创建了一个Looper和Looper对应的MessageQueue,由于主线程,单例的,所以Looper和MessageQueue也是但例的;

对于第二件事情:
知道了上面这些,我们就知道了Handler里面的mQueue实际就是上面创建的MessageQueue;
(知道了这两步,我们就可以让在主线程中发送消息,让子线程处理,虽然没有用,但是有助于理解)

接下来我们看到ActivityThread发现里面调用了Looper.loop()方法;我们就进一步看看这个loop方法:
也做了两件事情:
1、从消息队列中取出消息;(可能阻塞)queue.next(); // might block
2、Message.target.dispatch(Message)将消息发送出去;

第一件事情:
这里写图片描述
我们如果没有获取到消息,就通过JNI调用本地nativiePollOnce;让进程阻塞在这里;

第二件事情:
想明白这件事情的话,我们就需要知道message.target是什么东西。
我们在Handler里面的sendMessage发现了,其实际上就是一个handler;
也就是说,这里是调用handler的Dispatch()方法;
(这里我们就能明白一个道理,Handler和message,messsageQueue是一个多对一的关系,而且通过这样,可以保证每一个handler不会处理到其他的handler的消息;)

接下来我们就要看到最后一个流程了:
就是handler的sendMessage的方法:
里面也是做了两件事情:
1、将handler赋值给message.target
2、调用messageQueue的enqueueMessage方法:

第一件事情,之前已经说过了
第二件事情:
这里写图片描述

从MessageQueue的enqueueMessage方法我们是可以知道,下面几件事情:
1、如果我们的消息不是立马发送的,是不会唤醒主线程的,而且会将我们的消息按照Message.when在MessageQueue中进行一个排序;
2、能够排序,说明MessageQuene就不是一个队列,而是一个有序的单链表的结构,这里我在看开发艺术探索的时候,发现里面有提到过;
3、 如果是立马发送消息的话,会将通过nativeWake方法将线程给唤醒;让在上面next里面阻塞的进行,去处理消息;

这样就是基本的Handler的消息队列的源码分析;

目前还存在的问题如下:
1、不能明白Message.when到底是什么东西?在Message源码我们发现只是这个:readFromParcel这个方法里面有一个:when = source.readLong();
然后继续跟踪源码发现的是这个:

    public static final Parcelable.Creator<Message> CREATOR
            = new Parcelable.Creator<Message>() {
        public Message createFromParcel(Parcel source) {
            Message msg = Message.obtain();
            msg.readFromParcel(source);
            return msg;
        }

        public Message[] newArray(int size) {
            return new Message[size];
        }
    };

然后就找不到了,所以还不知道resource到底是个什么东西;
2、在enqueueMessage方法里面,如果不是立马发送消息,当Message的时间到了,谁会去调用这个方法呢?如果没有人调用的话,消息的发送时间不久耽误了吗?

欢迎各位大神解惑,小弟我先谢谢啦。

安卓交流群 :232748032

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值