Android源码之Handler(一)

在Android系统中,Handler是一个很重要的概念.可以说,在Android系统中,Handler的身影无处不在。
Handler提供了若干个构造函数,我们就从Handler的构造函数来开始分析Handler系统的实现. Handler的构造函数的实现如下:
[// Handler的构造函数
public Handler() {
        this(null, false);
    }
public Handler(Callback callback) {
        this(callback, false);
    }
public Handler(Looper looper) {
        this(looper, null, false);
    }
public Handler(Looper looper, Callback callback) {
        this(looper, callback, false);
    }
public Handler(boolean async) {
        this(null, async);
    }

public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
[// FIND_POTENTIAL_LEAKS
private static final boolean FIND_POTENTIAL_LEAKS = false;
FIND_POTENTIAL_LEAKS设置为true的时候, 会检测内存泄漏可能性.
]// FIND_POTENTIAL_LEAKS
    final Class<? extends Handler> klass = getClass();
    if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
    (klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
    klass.getCanonicalName());
    }
    [// if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0)
    检测内存泄漏是通过Java的反射机制来实现的.
    ]// if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0)
}
[// if (FIND_POTENTIAL_LEAKS)
这段代码是为了检测Handler可能的内存泄漏.当Handler被继承定义成匿名函数或者是某一类的内部类的时候,如果不把该Handler定义成static,则可能发生内存泄漏. 为什么呢?
因为不是static的内部类会默认持有一个指向父类的指针, 而发给这个Handler的Message又会持有这个Handler的指针. 这样如果这个Message不销毁的话,则这个Handler是不会被垃圾回收的.
]// if (FIND_POTENTIAL_LEAKS)

mLooper = Looper.myLooper();
[// mLooper = Looper.myLooper()
得到的是当前线程的Looper. 那么这个Looper是个什么呢?在这里我们先来看一下Looper的实现。
在Android系统中, Looper是按照如下方式使用的:
class LooperThread extends Thread {
                  *      public Handler mHandler;
                  *
                  *      public void run() {
                  *          Looper.prepare();
                  *
                  *          mHandler = new Handler() {
                  *              public void handleMessage(Message msg) {
                  *                  // process incoming messages here
                  *              }
                  *          };
                  *
                  *          Looper.loop();
                  *      }
                  *  }
            由上面的代码可以看出, 使用Looper要先调用Looper.prepare函数, 然后构造一个Handler对象,最后调用Looper.loop函数。经过上面的过程之后,就可以利用Handler机制来发送和处理消息了。
我们先来看一下prepare的实现:
public static void prepare() {
                        prepare(true);
                    }

               private static void prepare(boolean quitAllowed) {
                if (sThreadLocal.get() != null) {
                [// if (sThreadLocal.get() != null)
                   这里首先会先判断之前是否已经为线程设置过Looper
                    sThreadLocal是Looper内部定义的一个static成员变量,定义如下:
                    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
                    ThreadLocal的构造函数定义如下:
                    [// ThreadLocal的构造函数
                    public ThreadLocal() {}
                    由此可见,ThreadLocal的构造函数是个空函数,什么也不做。
                    ]// ThreadLocal的构造函数
注意,这里的成员变量sThreadLocal是static的。
我们接下来看一下ThreadLocal的get函数的实现:
public T get() {
                        // Optimized for the fast path.
                       Thread currentThread = Thread.currentThread();
                       [// Thread currentThread = Thread.currentThread()
                       这里调用Thread的currentThread函数当得到当前线程。
                       ]// Thread currentThread = Thread.currentThread()
                         Values values = values(currentThread);
                         [// Values values = values(currentThread)
                         当得到了当前线程的Thread变量之后, 会调用values函数。values函数的定义如下:
                         Values values(Thread current) {
                                return current.localValues;
                              }
                              values函数会直接返回Thread变量的localValues变量,由此可知,其实TheadLocal机制其实是将值保存到每一个Thread变量中去的.
                         ]// Values values = values(currentThread)
                           if (values != null) {
                           [// if (values != null)
                             下面这段代码是在当前线程的localValues成员变量中取ThreadLocal保存的值。
                            ]// if (values != null)
                            Object[] table = values.table;
                               int index = hash & values.mask;
                               [// int index = hash & values.mask
                               这句代码实在计算索引值。mask的值就是Hash Table的长度。那么这个hash变量的值是如何计算的呢?
                               我们看一下hash成员变量是如何初始化的?
                               private final int hash = hashCounter.getAndAdd(0x61c88647 * 2);
                               private static AtomicInteger hashCounter = new AtomicInteger(0);
                               我们看到, hash成员变量是final的,并且是非static的。也就是说每一个ThreadLocal对象持有一个hash变量。更进一步,我们可以得到这样的结论:对于某一类的ThreadLocal变量(通俗的讲就是ThreadLocal的模版参数一样),其实维护的是一个hash变量值,也就是说会映射到同一个索引的地方去。
                               ]// int index = hash & values.mask
                               if (this.reference == table[index]) {
                               return (T) table[index + 1];
                              }
                              [// if (this.reference == table[index])
                              在Values的实现中,table会在index保存ThreadLocal对象,而在index+1的位置保存ThreadLocal的值。为什么要这么设计呢?
                              我们先来看一下reference的定义:
                              private final Reference<ThreadLocal<T>> reference = new WeakReference<ThreadLocal<T>>(this);
                              可以看到reference是个弱引用。所以这里要先比较一下reference和table[index]. 是为了防止内存回收。
                              ]// if (this.reference == table[index])

                           } else {
                            values = initializeValues(currentThread);
                            [// values = initializeValues(currentThread)
                            Values initializeValues(Thread current) {
                                return current.localValues = new Values();
                                [// new Values()
                                Values类是ThreadLocal的一个内部类, 其实它的作用就是一个Hash Table. 我们先来看一下Values的构造函数:
                                Values() {
                                            initializeTable(INITIAL_SIZE);
                                            [// initializeTable(INITIAL_SIZE)
private void initializeTable(int capacity) {
                                                    this.table = new Object[capacity * 2];
                                                       this.mask = table.length - 1;
                                                       this.clean = 0;
                                                        this.maximumLoad = capacity * 2 / 3; // 2/3
                                                    }
                                                    initializeTable函数就是初始化Values的几个重要的成员变量。
                                                    INITIAL_SIZE是Values定义的常量。
                                                    private static final int INITIAL_SIZE = 16;
                                            ]// initializeTable(INITIAL_SIZE)
                                               this.size = 0;
                                               this.tombstones = 0;
                                            }

                                ]// new Values()
                                  }
                                  如果当前线程还没有设置过localValues,  则会创建一个Values对象,并赋值给当前线程。
                            ]// values = initializeValues(currentThread)
                           }
                           return (T) values.getAfterMiss(this);
                           [// values.getAfterMiss(this)
当第一个索引位置没有得到值的情况下或者第一次设置Values成员变量,则会调用getAfterMiss来尝试查找有冲突的情况下的值:
Object getAfterMiss(ThreadLocal<?> key) {
                                Object[] table = this.table;
                                  int index = key.hash & mask;

                                   if (table[index] == null) {
                                   [// if (table[index] == null)
                                   如果table的index索引的位置的值是null, 则说明没有发生过冲突,也就没有必要在继续查找index之后的位置
                                   ]// if (table[index] == null)
                                    Object value = key.initialValue();
                                    [// Object value = key.initialValue();
                                    这里会调用ThreadLocal的initialValue函数来初始化一个值
                                    protected T initialValue() {
                                           return null;
                                           }
                                           默认的initialValue函数的实现就是返回null
                                    ]// Object value = key.initialValue();

                                       if (this.table == table && table[index] == null) {
                                       [// if (this.table == table && table[index] == null)
                                       这里为什么还要判断一下?是为了防止在initialValue函数中改变了table, 如果发现没有改变,则设置
                                       ]// if (this.table == table && table[index] == null)
                                        table[index] = key.reference;
                                         table[index + 1] = value;
                                         size++;

                                          cleanUp();
                                          [// cleanUp()
这里还会调用cleanUp函数来清空失效的
private void cleanUp() {
                                                if (rehash()) {
[// if (rehash())
这里会先判断是否需要rehash。如果rehash了,则不必往下进行了.rehash函数的定义如下:
private boolean rehash() {
                                                            if (tombstones + size < maximumLoad) {
                                                                return false;
                                                               }
                                                               [// if (tombstones + size < maximumLoad)
                                                               tombstones + size表示目前装载的数目
                                                               ]// if (tombstones + size < maximumLoad)

                                                                int capacity = table.length >> 1;
                                                                [// int capacity = table.length >> 1
                                                                因为在hash table中, 其实是用两个位置来表示一个真正的值的。因此容量就应该为table的长度的一半。
                                                                ]// int capacity = table.length >> 1
int newCapacity = capacity;
                                                                if (size > (capacity >> 1)) {
                                                                newCapacity = capacity * 2;
                                                                }
                                                                [// if (size > (capacity >> 1))
                                                                上面这段代码是判断是否需要扩充hash table的容量。条件就是现在有效的值的个数已经超过了容量的一半。
                                                                ]// if (size > (capacity >> 1))

                                                                Object[] oldTable = this.table;
                                                               initializeTable(newCapacity);
                                                            this.tombstones = 0;
                                                            [// this.tombstones = 0;
                                                            这里是初始化了一个新的hash table
                                                            ]// this.tombstones = 0;

                                                                if (size == 0) {
                                                             return true;
                                                              }
                                                              [// if (size == 0)
                                                              如果当前没有有效的值,这直接返回
                                                              ]// if (size == 0)


                                                            for (int i = oldTable.length - 2; i >= 0; i -= 2) {
                                                            [// for (int i = oldTable.length - 2; i >= 0; i -= 2)
                                                                在这个for循环里,将老的hash table里的值拷贝到新的hash table中去
                                                               ]// for (int i = oldTable.length - 2; i >= 0; i -= 2)

                                                                Object k = oldTable[i];
                                                                  if (k == null || k == TOMBSTONE) {
                                                                    continue;
                                                                   }
                                                                   [// if (k == null || k == TOMBSTONE)
                                                                   如果发现是无效的则跳过
                                                                   ]// if (k == null || k == TOMBSTONE)

                                                                    @SuppressWarnings("unchecked")
                                                                    Reference<ThreadLocal<?>> reference = (Reference<ThreadLocal<?>>) k;
                                                                    ThreadLocal<?> key = reference.get();
                                                                    if (key != null) {
                                                                    [// if (key != null)
                                                                    如果这个ThreadLocal对象没有被回收,还是有效的,则将这个值放到新的hash table中去
                                                                    ]// if (key != null)
                                                                    add(key, oldTable[i + 1]);
                                                                    [// add(key, oldTable[i + 1])
                                                                    调用add函数来增加一个值. add函数的定义如下:
                                                                    void add(ThreadLocal<?> key, Object value) {
                                                                            for (int index = key.hash & mask;; index = next(index)) {
                                                                            [// for (int index = key.hash & mask;; index = next(index))
                                                                            for循环查找一个可以插入的位置。初始的索引是用ThreadLocal的hash变量的值和Values的成员变量mask做与运算。由此可以看出,一类的ThreadLocal的值是放在一个索引位置上的。
                                                                            next函数是计算下一个索引位置。next函数的定义如下:
private int next(int index) {
                                                                                   return (index + 2) & mask;
                                                                                    }
                                                                                    正如我们之前分析的那样,在hash table中其实是用两个位置来表示一个值的。
                                                                            ]// for (int index = key.hash & mask;; index = next(index))
                                                                                Object k = table[index];
                                                                                    if (k == null) {
                                                                                    table[index] = key.reference;
                                                                                      table[index + 1] = value;
                                                                                       return;
                                                                                 }
                                                                                 [// if (k == null)
发现一个空位置,则将值写入到这里。
                                                                                 ]// if (k == null)
                                                                               }
                                                                          }

                                                                    ]// add(key, oldTable[i + 1])
                                                                    } else {
                                                                    [// else
                                                                    这里是表示垃圾回收的情况
                                                                    ]// else
                                                                    size--;
                                                                    }
                                                             }
                                                                return true;
                                                           }

]// if (rehash())
                                                     return;
                                               }

                                                    if (size == 0) {
                                               return;
                                                    }
                                                    [// if (size == 0)
                                                    size为0表示有效的值为空,则不需要往下进行了
                                                    ]// if (size == 0)

                                                    int index = clean;
                                                    [// int index = clean
                                                    在Values类的设计中,有一个成员变量clean, 记录上次清理结束的位置。为什么要记录这个位置呢?效率会高多少呢?
                                                    ]// int index = clean
                                                  Object[] table = this.table;
                                                    for (int counter = table.length; counter > 0; counter >>= 1, index = next(index)) {
                                                       Object k = table[index];

                                                        if (k == TOMBSTONE || k == null) {
                                                           continue; // on to next entry
                                                          }

                                                            @SuppressWarnings("unchecked")
                                                            Reference<ThreadLocal<?>> reference = (Reference<ThreadLocal<?>>) k;
                                                            if (reference.get() == null) {
                                                            table[index] = TOMBSTONE;
                                                            table[index + 1] = null;
                                                             tombstones++;
                                                            size--;
                                                            }
                                                            [// if (reference.get() == null)
                                                            这里发现被垃圾回收的,则将这个位置标记为TOMBSTONE.
                                                            ]// if (reference.get() == null)
                                                        }

                                                   clean = index;
                                                   [// clean = index
                                                   记录下次清理的位置
                                                   ]// clean = index
                                               }
                                          ]// cleanUp()
                                           return value;
                                      }

                                        // The table changed during initialValue().
                                       put(key, value);
                                       [// put(key, value)
                                       如果发现在调用initialValue函数过程中, hash table已经发生了改变,则直接将这个值插入到hash table中.
                                       put函数的实现如下:
                                       void put(ThreadLocal<?> key, Object value) {
                                            cleanUp();
                                            [// cleanUp()
                                            put函数首先调用cleanUp函数
                                            ]// cleanUp()


                                              int firstTombstone = -1;
[// int firstTombstone = -1
这里用一个变量firstTombstone记录发现的第一个TOMBSTONE的位置,为什么要记录这个位置呢?因为TOMBSTONE表示被垃圾回收之后的对该位置的表示。
]// int firstTombstone = -1
                                               for (int index = key.hash & mask;; index = next(index)) {
                                                Object k = table[index];

                                                    if (k == key.reference) {
                                                   table[index + 1] = value;
                                                        return;
                                                    }
                                                    [// if (k == key.reference)
                                                    这里发现了同样一个ThreadLocal对象,则直接替换值
                                                    ]// if (k == key.reference)

                                               if (k == null) {
                                                    if (firstTombstone == -1) {
                                                        // Fill in null slot.
                                                           table[index] = key.reference;
                                                         table[index + 1] = value;
                                                         size++;
                                                          return;
                                                     }

                                                      // Go back and replace first tombstone.
                                                      table[firstTombstone] = key.reference;
                                                      table[firstTombstone + 1] = value;
                                                      tombstones--;
                                                      size++;
                                                       return;
                                                   }
                                                   [// if (k == null)
                                                   如果当前索引值位置的值为null,则说明发现了一个没有用过的位置,则不必继续搜索了。这里还会将值保存到合适的索引值的位置上去。
                                                   ]// if (k == null)

                                                   // Remember first tombstone.
                                                  if (firstTombstone == -1 && k == TOMBSTONE) {
                                                  firstTombstone = index;
                                                  }
                                             }
                                           }
                                       ]// put(key, value)
                                       return value;
                                  }

                                   int firstTombstone = -1;
                                 for (index = next(index);; index = next(index)) {
                                    Object reference = table[index];
                                        if (reference == key.reference) {
                                        return table[index + 1];
                                        }

                                        if (reference == null) {
                                        Object value = key.initialValue();

                                            if (this.table == table) {
                                          if (firstTombstone > -1 && table[firstTombstone] == TOMBSTONE) {
                                                table[firstTombstone] = key.reference;
                                                   table[firstTombstone + 1] = value;
                                                    tombstones--;
                                                  size++;

                                                   return value;
                                         }


                                           if (table[index] == null) {
                                                table[index] = key.reference;
                                                 table[index + 1] = value;
                                                size++;

                                                  cleanUp();
                                                   return value;
                                                }
                                           }

                                           put(key, value);
                                            return value;
                                       }

                                     if (firstTombstone == -1 && reference == TOMBSTONE) {
                                        firstTombstone = index;
                                      }
                                }
                                [// for (index = next(index);; index = next(index))
                                上面这段代码是不是看着很眼熟,和put函数中的实现是相似的。
                                ]// for (index = next(index);; index = next(index))
                               }

                           ]// values.getAfterMiss(this)
                      }
                    ]// if (sThreadLocal.get() != null)

                            throw new RuntimeException("Only one Looper may be created per thread");
                   }

                   sThreadLocal.set(new Looper(quitAllowed));
                   [// sThreadLocal.set(new Looper(quitAllowed))
如果sThreadLocal.get函数为null, 则说明还没有为当前线程设置过Looper对象,则这里就调用ThreadLocal的set函数来为当前线程new一个Looper对象。
我们先来看一下Looper的构造函数:
private Looper(boolean quitAllowed) {
                        mQueue = new MessageQueue(quitAllowed);
                        [// mQueue = new MessageQueue(quitAllowed)
                        在Looper类中,有一个MessageQueue的成员变量mQueue,定义如下:
                        final MessageQueue mQueue;
                        也就是说每一个Looper内部维护了一个MessageQueue。
我们看一下MessageQueue的构造函数:
MessageQueue(boolean quitAllowed) {
                               mQuitAllowed = quitAllowed;
                               mPtr = nativeInit();
                               [// mPtr = nativeInit()
这里会调用nativeInit()函数。从名字可以猜测这是个native函数。
private native static long nativeInit();
果不其然,确实是个native函数。
调用nativeInit函数其实是调用的android_os_MessageQueue.cpp(为与/home/yaojian/AndroidSource/frameworks/base/core/jni文件夹下)的android_os_MessageQueue_nativeInit函数:
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
                                            NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
                                            [// NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue()
                                           这里会创建一个C++层的NativeMessageQueue的对象。
                                           我们先来看一下NativeMessageQueue的类结构:
                                           class NativeMessageQueue : public MessageQueue
                                           class MessageQueue : public RefBase
                                           MessageQueue继承自RefBase类,由此可知可以用智能指针来管理MessageQueue类。
                                           我们再来看一下NativeMessageQueue类的构造函数:
                                           MessageQueue::MessageQueue() {
                                                }
                                                NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
                                                    mLooper = Looper::getForThread();
                                                    [// mLooper = Looper::getForThread()
                                                    在NativeMessageQueue类中也有一个Looper类型的成员变量mLooper, mLooper的定义如下:
                                                    sp<Looper> mLooper;
                                                    这里mLooper的初始化是通过Looper的getForThread函数来实现的:
                                                    sp<Looper> Looper::getForThread() {
                                                            int result = pthread_once(&gTLSOnce, initTLSKey);
                                                            [// int result = pthread_once(&gTLSOnce, initTLSKey)
                                                            这里这个pthread_once函数是干什么的呢?我也不知道,百度一下查出下面的解释:
                                                            int pthread_once(pthread_once_t *once_control, void (*init_routine) (void))
                                                            本函数使用初值为PTHREAD_ONCE_INIT的once_control变量保证init_routine()函数在本进程执行序列中仅执行一次。
                                                            也就是说pthread_once保证了initTLSKey函数之调用一次,gTLSOnce和initTLSKey的定义如下:
                                                            static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
                                                            initTLSKey函数的实现如下:
                                                                void Looper::initTLSKey() {
                                                                    int result = pthread_key_create(&gTLSKey, threadDestructor);
                                                                    [// int result = pthread_key_create(&gTLSKey, threadDestructor)
                                                                    在initTLSKey函数中,会调用pthread_key_create函数。那么这个pthread_key_create函数有什么作用么?我也不知道啊?还是百度一下吧:
                                                                    int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
                                                                    函数 pthread_key_create() 用来创建线程私有数据。该函数从 TSD 池中分配一项,将其地址值赋给 key 供以后访问使用。第 2 个参数是一个销毁函数,它是可选的,可以为 NULL,为 NULL 时,则系统调用默认的销毁函数进行相关的数据注销。如果不为空,则在线程退出时(调用 pthread_exit() 函数)时将以 key 锁关联的数据作为参数调用它,以释放分配的缓冲区,或是关闭文件流等。
gTLSKey和threadDestructor的定义如下:
                                                                    static pthread_key_t gTLSKey = 0;
                                                                    void Looper::threadDestructor(void *st) {
                                                                            Looper* const self = static_cast<Looper*>(st);
                                                                            if (self != NULL) {
                                                                                self->decStrong((void*)threadDestructor);
                                                                            }
                                                                        }
                                                                    ]// int result = pthread_key_create(&gTLSKey, threadDestructor)
                                                                    LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
                                                                }
                                                            ]// int result = pthread_once(&gTLSOnce, initTLSKey)
                                                            LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");

                                                            return (Looper*)pthread_getspecific(gTLSKey);
                                                            [// return (Looper*)pthread_getspecific(gTLSKey)
                                                            在getForThread函数的最后会调用pthread_getspecific函数。那pthread_getspecific函数是干什么呢?又一次不知道,这次我决定不求助百度了,求助Google:
void *pthread_getspecific(pthread_key_t key);
函数 pthread_getspecific() 将与 key 相关联的数据读出来。返回的数据类型都是 void *,因此可以指向任何类型的数据。
                                                            ]// return (Looper*)pthread_getspecific(gTLSKey)
                                                        }
                                                        [// sp<Looper> Looper::getForThread()
                                                        通过分析getForThread函数的实现,我们发现其实这个ThreadLocal的实现是很相似的。
                                                        那为什么还在C++层在实现一套呢?现在还不知道啊.
                                                        ]// sp<Looper> Looper::getForThread()
                                                    ]// mLooper = Looper::getForThread()
                                                    if (mLooper == NULL) {
                                                    [// if (mLooper == NULL)
                                                    这里如果当前线程的Looper返回的空,则要为当前线程设置一个新的Looper对象
                                                    ]// if (mLooper == NULL)
                                                        mLooper = new Looper(false);
                                                        [// mLooper = new Looper(false)
这里会先new一个C++层的Looper对象。我们看一下Looper的构造函数:
Looper::Looper(bool allowNonCallbacks) :
                                                                    mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
                                                                    mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
                                                                int wakeFds[2];
                                                                int result = pipe(wakeFds);
                                                                LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);

                                                                mWakeReadPipeFd = wakeFds[0];
                                                                mWakeWritePipeFd = wakeFds[1];

                                                                result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
                                                                LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
                                                                        errno);

                                                                result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
                                                                LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
                                                                        errno);

                                                                mIdling = false;

                                                                // Allocate the epoll instance and register the wake pipe.
                                                                mEpollFd = epoll_create(EPOLL_SIZE_HINT);
                                                                LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);

                                                                struct epoll_event eventItem;
                                                                memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
                                                                eventItem.events = EPOLLIN;
                                                                eventItem.data.fd = mWakeReadPipeFd;
                                                                result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
                                                                LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
                                                                        errno);
                                                            }
                                                            在Looper的构造函数中,会创建两个管道:mWakeReadPipeFd和mWakeWritePipeFd。并且利用epoll机制来设置监听mWakeReadPipeFd。
                                                        ]// mLooper = new Looper(false)
                                                        Looper::setForThread(mLooper);
                                                        [// Looper::setForThread(mLooper)
                                                        当创建完C++层的Looper对象之后,就可以调用setForThread函数来将该对象设置到当前线程中去。
                                                        void Looper::setForThread(const sp<Looper>& looper) {
                                                                sp<Looper> old = getForThread(); // also has side-effect of initializing TLS

                                                                if (looper != NULL) {
                                                                    looper->incStrong((void*)threadDestructor);
                                                                }

                                                                pthread_setspecific(gTLSKey, looper.get());

                                                                if (old != NULL) {
                                                                    old->decStrong((void*)threadDestructor);
                                                                }
                                                            }
                                                        ]// Looper::setForThread(mLooper)
                                                    }
                                                }
                                            ]// NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue()
                                            if (!nativeMessageQueue) {
                                                jniThrowRuntimeException(env, "Unable to allocate native queue");
                                                return 0;
                                            }

                                            nativeMessageQueue->incStrong(env);
                                            return reinterpret_cast<jlong>(nativeMessageQueue);
                                        }
                                        当创建完C++层的NativeMessageQueue之后,就得到这个C++层的NativeMessageQueue的句柄,并赋值给成员变量mPtr. mPtr的定义如下:
                                        private long mPtr; // used by native code
                                        由此得出结论,每一个Java层的MessageQueue对象在C++曾都有一个NativeMessageQueue对象。
                               ]// mPtr = nativeInit()
                               }
                        ]// mQueue = new MessageQueue(quitAllowed)
                       mThread = Thread.currentThread();
                       }
                       [// private Looper(boolean quitAllowed)
                       首先我们注意到Looper的构造函数是private的。
                       ]// private Looper(boolean quitAllowed)

当构造完Looper对象之后,就会调用ThreadLocal的set函数来将该Looper对象保存到当前线程的ThreadLocal中去。
我们来看一下ThreadLocal类的set函数的实现:
public void set(T value) {
                       Thread currentThread = Thread.currentThread();
                           Values values = values(currentThread);
                           if (values == null) {
                           values = initializeValues(currentThread);
                           }
                           values.put(this, value);
                       }
                       [// public void set(T value)
                       set函数的实现还是比较清晰的,里面调用的函数我们之前都分析过。
                       ]// public void set(T value)

                   ]// sThreadLocal.set(new Looper(quitAllowed))
              }

猜你喜欢

转载自zzu-007.iteye.com/blog/2261354