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接口,
到这里就都分析完了,再次强调说的不好或者说的不准确的地方欢迎指正哦。