Handler源码解析基于ThreadLocal来进行分析

来源:互联网 发布:桌面规划软件 编辑:程序博客网 时间:2024/06/05 03:03

Handler源码解析基于ThreadLocal来进行分析

/**
* Default constructor associates this handler with the {@link Looper} for the
* current thread.
*
* If this thread does not have a looper, this handler won’t be able to receive messages
* so an exception is thrown.
*/

public Handler() {        this(null, false);    }

根据注释解析我们可以知道,默认的Handler构造函数是需要一个Looper对象的,针对当前线程,如果当前线程没有looper,那么这个handler将无法接收到message消息,我们继续跟踪到Looper源码中去获悉对应信息。


Looper
/*
* API Implementation Note:
*
* This class contains the code required to set up and manage an event loop
* based on MessageQueue. APIs that affect the state of the queue should be
* defined on MessageQueue or Handler rather than on Looper itself. For example,
* idle handlers and sync barriers are defined on the queue whereas preparing the
* thread, looping, and quitting are defined on the looper.
*/
这段是关于Looper的代码注释,大概意思是Looper是设置和管理事件循环机制所需的代码

    private static final String TAG = "Looper";    // sThreadLocal.get() will return null unless you've called prepare().    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();    private static Looper sMainLooper;  // guarded by Looper.class    final MessageQueue mQueue;    final Thread mThread;

从代码块中,我们可以明显看到定义了ThreadLocal传递了Looper的泛型,以及sMainLooper,字面意思暂且认定为主线程的looper,以及MessageQueue


继续跟踪代码可以看到
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/

    public static void prepare() {        prepare(true);    }    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));    }

初始化当前线程作来指向一个Looper对象,通过prepare(true)我们可以看到sThreadLocal.get()这里进行了非空判断,并抛出了异常Only one Looper may be created per thread 每个线程只能有一个Looper对象,继续看源码


/**
* Returns the value in the current thread’s copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread’s value of this thread-local
*/

    public T get() {        Thread t = Thread.currentThread();        ThreadLocalMap map = getMap(t);        if (map != null) {            ThreadLocalMap.Entry e = map.getEntry(this);            if (e != null)                return (T)e.value;        }        return setInitialValue();    }

sThreadLocal.get()这个方法原来获取的就是Thread.currentThread();当前线程的对象,通过这一系列的代码跟踪,我们可以大致得出结论,Handler在初始化的时候会得到一个Looper对象,而这个Looper对象就是通过主线程创建的,而主线程的ThreadLocal刚好起到联系Handler+Looper对象的关系。这里写图片描述


今天就先分析这么多,上班任务很多,有不对的地方,望一起讨论吧,到这里,我们已经可以初步得知Handler跟Looper是怎么建立关联的了,通过ThreadLocal进行关联的。这也是之前去美柚面试的时候被问到的一道面试题。欢迎补充,晚点继续更新!
By Aaron_Lian

1 0
原创粉丝点击