说到handler大家都很熟悉,自己也用了很久,再此总结一下 从handler的源码角度看看handler是如何执行的。
涉及到的内容: Loop Message MessageQueue ThreadLocal Handler
Looper的相关问题 先看一下new Handler();的源码 带我们了解looper; 创建Handler对象时,在构造方法中会获取Looper和MessageQueue的对象
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
...省略部分代码..
mLooper = Looper.myLooper();//这里获取一个mLooper
if (mLooper == null) {//如果mLooper为null抛出异常
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
看到这里知道了。在使用new Handler()之前必须要有一个mLooper这个对象。不然的话会抛出异常。 接着看
public static @Nullable Looper myLooper() {//这里就返回一个mLooper 了 return sThreadLocal.get(); }
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
这里有个注意的就是ThreadLocal 这个类 就是每次创建一次都会有一个单独的线程出现,每个线程自己做自己的事情 互不干扰。其实呢这个Looper就是为了在该线程中 创建一个messageQueue。然后后面是把handler放到message中。然后再把message放到了messageQueue中。这样 这个handler就可以发送和接受 在该线程中的所有操作了。如果还不理解ThreadLocal的意思。请自行搜索。
比如你有一个主线程和10个子线程,现在呢这11个线程里面都new Handler()。就会有11个不同的ThreadLocal。他们之前不顾干扰。然后呢你就需要在这10个子线程里面写都写一遍Looper.prepare()和Looper.loop()。
比如你有一个主线程和10个子线程,现在呢这11个线程里面都new Handler()。就会有11个不同的ThreadLocal。他们之前不顾干扰。然后呢你就需要在这10个子线程里面写都写一遍Looper.prepare()和Looper.loop()。
我们现在已经有了获取looper的方法了。肯定也得有set的方法。 看 Looper.prepare();方法
public static void prepare() { prepare(true); }
private static void prepare(boolean quitAllowed) {//这个参数的意思就是这个messagequeue是否可以销毁
if (sThreadLocal.get() != null) {//这里执行了获取ThreadLocal方法。如果已经存在了抛异常。所以 prepare方法在一个线程里只能执行一遍。
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed)); //这里执行了我们想要的set方法。
}
//这个looper方法里面直接new出来了 MessageQueue() 和获取当前线程作为 标示 private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
// True if the message queue can be quit. private final boolean mQuitAllowed;//这里是判断该messageQueue是否可销毁 MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;//赋值
mPtr = nativeInit();
}
Looper和MessageQueue是通过Looper.prepare的时候创建的,在一个线程里面prepare()只能执行一次 从这里我们可以看出来 new Handler();10次。会有10个Threadlocal,会有10个MessageQueue。 到这里我们还有个疑问就是为什么主线程没有写Looper.prepare();
原因是:ActivityThread.java里面在执行main方法的时候,已经对主线程的Looper进行了初始化。
到这里就明白了为什么 子线程执行 Looper.prepare()方法了。 再来看Looper.loop();
public static void loop() {
final Looper me = myLooper();//获取looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;//获取该looper下的queue
。。。。。。
for (;;) {//死循环。我看的源码是api 23的。记得以前是while(true)。为什么捏
Message msg = queue.next(); // might block 可能会阻塞
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
。。。。。
msg.target.dispatchMessage(msg);//这个方法很重要
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
这个Looper.loop()方法就是一个死循环不断地从messageQueue中获取msg
