其实问这种问题,无非就是想知道你对handler了解怎么样。虽然handler这种问题已经被问烂了,可是不少公司,尤为是中小型企业,面试
被问的概率仍是很高,因此,再次记录一下,也很简单,没事儿的时候点进源码看看就明白。多线程
Android 的 多线程通信核心类是Handler!async
一般咱们在使用多线程通信的方式,是在 线程A(或UI线程) 中建立 handler,在线程B中 使用 handler的实例,调用其方法 例如:
sendMessage(Message msg)
、sendEmptyMessage(int what)
,发送咱们须要传送的数据放进了Messagequeue里面。而后被主线程或者是实例化化handler的线程 的Looper循环到,而后执行。ide
经过源码咱们大体能够理出一条线路来:oop
须要注意的是,
ThreadLocal
该类是用于建立线程局部变量的类,咱们知道,一般状况下一个变量是在多个线程中都能访问的,可是ThreadLocal,可建立一个只在当前线程访问的变量。他支持泛型,回到咱们的面试题上ui
这里 咱们能够逐步分析:this
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();
,spa
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)
的时候:code
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里面进行循环!