其实问这种问题,无非就是想知道你对handler了解怎么样。虽然handler这种问题已经被问烂了,但是很多公司,尤其是中小型企业,
被问的几率还是很高,所以,再次记录一下,也很简单,没事儿的时候点进源码看看就明白。
Android 的 多线程通讯核心类是Handler!
通常我们在使用多线程通讯的方式,是在 线程A(或UI线程) 中创建 handler,在线程B中 使用 handler的实例,调用其方法 例如:
sendMessage(Message msg)
、sendEmptyMessage(int what)
,发送我们需要传送的数据放进了Messagequeue里面。然后被主线程或者是实例化化handler的线程 的Looper循环到,然后执行。
通过源码我们大致可以理出一条线路来:
需要注意的是,
ThreadLocal
该类是用于创建线程局部变量的类,我们知道,通常情况下一个变量是在多个线程中都能访问的,但是ThreadLocal,可创建一个只在当前线程访问的变量。他支持泛型,回到我们的面试题上
这里 我们可以逐步分析:
public Handler(Callback callback, boolean async) {
//得到主线程(已经被ActivityThread初始化好)的looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//得到主线程(已经被ActivityThread初始化好)的looper的MessageQueue,注释:①
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
注意,看到了吗? 这里是核心:
mLooper = Looper.myLooper();
,
public static Looper myLooper() {
return sThreadLocal.get();
}
而这个Looper对象,是在我们启动程序的时候,也就是ActivityThread 中的main方法帮我们初始化的,也就是我们主线程的Looper。
public static void prepareMainLooper() {
···
prepare(false);
···
}
--------------------------------------------------
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
我们在子线程 使用 handler的实例进行 sendMessage(Message msg)
的时候:
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
//这里的代码和上面的注释①对应。
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
最终走向enqueueMessage
:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
最终把我们的Message,放进了主线程的MessageQueue里面进行循环!