『 面试题 』之 Android中的消息机制?

其实问这种问题,无非就是想知道你对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里面进行循环!

相关文章
相关标签/搜索