Looper与线程之间的关系:
一直没有搞得很清楚,今天有时间,翻了一下源码,记录过程
/*
* class : Looper
*/
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
请注意, sThreadLocal是一个static对象, 所有的Looper将共用一个sThreadLocal对象
当我们想为自己的进程创建自己的Looper的时候,应该调用下面这个函数,我们看看这个函数做了些什么:
/*
* class : Looper
*/
private static void prepare(boolean quitAllowed) {
//先看看当前线程是否已经有了自己的Looper,有的话将抛出异常。
//第一次将获取null
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//没有的话则创建一个新的Looper,并将这个新的Looper通过sThreadLocal与当前线程绑定
sThreadLocal.set(new Looper(quitAllowed));
}
/*
* class : ThreadLocal
*/
public void set(T value) {
//获取当前线程对象
Thread t = Thread.currentThread();
//获取当前线程的threadLocals成员变量,其类型是ThreadLocal.ThreadLocalMap
ThreadLocalMap map = getMap(t);
if (map != null)
//this : sThreadLocal,ThreadLocal<Looper>的对象,请记住sThreadLocal是一个静态对象
//value : Looper的对象
map.set(this, value)
else
createMap(t, value);
}
/*
* class : ThreadLocal
*/
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
/*
* class : Thread
*/
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* class : ThreadLocalMap
*/
private void set(ThreadLocal key, Object value) {
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
//遍历整个table
for (Entry e = tab[i];e != null;e = tab[i = nextIndex(i, len)]) {
ThreadLocal k = e.get();
//如果已经存在,则更新
if (k == key) {
e.value = value;
return;
}
//如果table是空项,则使用key和value更新
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
//这里给出Entry的定义
/*
* class : ThreadLocalMap
*/
static class Entry extends WeakReference<ThreadLocal> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}
整个流程看完下来,整个设计就比较清楚了。
1 每个线程都有ThreadLocal.ThreadLocalMap threadLocals = null;这样一个成员变量,这个变量的用途就在于维护各线程自有的对象的
2 threadLocals对应有一个Entry的table,
3 Looper只是某一种每个线程需要维护的对象,所以它将是Entry table的一项。其中,以ThreadLocal<Looper>类型的对象sThreadLocal为key,以Looper对象为value。
如果还有其他的需要每个线程维护的对象,将与Looper类似。