Looper 记录

记录一下looper 创建流程以及looper 保持主线程唯一的机制

looper 的创建是在SystemServer中创建的:
SystemServer 的main 入口

   public static void main(String[] args) {
        new SystemServer().run();
    }
 private void run() {
         //其他服务的创建
          Looper.prepareMainLooper();

        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

在run方法中 会看到我们熟悉的两个方法:1 Looper.prepareMainLooper() 创建方法 和
2.Looper.loop(); 循环方法。下面会去剖析这两个方法写作用!


prepareMainLooper()

 /**
     * Initialize the current thread as a looper, marking it as an
     * application's main looper. The main looper for your application
     * is created by the Android environment, so you should never need
     * to call this function yourself.  See also: {@link #prepare()}
     */
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

注释主要说的是,这是Looper 是主程序分配创建的,不需要开发者自己手动创建,也就是说,每个Application在创建启动的时候,都会主动在主线程创建一个looper对象。
而prepareMainLooper中主要做两件事情:1:prepare(false) 2: sMainLooper = myLooper();


1.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));
    }

通过抛出的异常可以得知:prepare 这个方法主要是为了通过ThreadLocal 保持Looper对象的唯一性的!而ThreadLocal 结构和如何保持唯一性的呢后面会专门分析的!

  private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

在构造方法中创建MessageQueue的作用其实就很简单了,也是为了唯一性,一个Looper对应一个MessageQueue 队列!
而Thread.currentThread() 就是获取当前线程
以上的就是Looper的创建过程 总结来说就是:
先通过ThreadLocal.get 去取,有的话 会抛出异常,没有的话会创建,创建一个looper 不是直接用的,而是先将looper 对象存入ThreadLocal中,然后通过myLooper() 去取Looper对象出来!

 public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

ThreadLocal

ThreadLocal 对于Looper 来说是非常的重要的,当然,不要看到Thread就觉得它是个线程,其实来说,ThreadLocal就是一个容器。下面来看看 ,在源码中ThreadLocal主要做的是什么工作的吧。
首先在Looper的全局变量中会看到这么一个:

static final ThreadLocal sThreadLocal = new ThreadLocal();


这么看是不是很熟悉,其实就是一个Map!当然后面会有更多的证据去表面它就是一个Map身份
下面先看看它是如何在Looper中使用的。
在上面说到prepare中会通过sThreadLocal.get去取出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) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

注释大概意思就是通过当前线程作为key返回对应的value,而这个value就是ThreadLocalMap 对象。ThreadLocalMap是什么呢?

  /**
         * The entries in this hash map extend WeakReference, using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced, so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
 static class Entry extends WeakReference> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

ThreadLocalMap内部维护了一个key-value键值对的Entry 类! 而且是通过软引用进行引用的!
通过Entry ,而在ThreadLocal 的get方法中,通过当前本地的线程作为key 会取得当前的ThreadLocalMap,
...未完待续

你可能感兴趣的:(Looper 记录)