经常看到Android的消息用法大概为:
Looper.prepare()
Looper.myLooper();
xxxHandler = new Handler() {
handleMessage(Message msg){...}
};
Looper.loop();
刚开始搞不清楚状况, 根据名字完全看不出有什么关系的两个类,到底如何进行消息传递呢? 只是知道就这么用就没问题的, 应该不少人跟我一样吧.
如然有兴趣来解刨一下吧.
Looper.prepare(); 里面有一句 sThreadLocal.set(new Looper());
这里就new 了一个Looper了, 然后放到ThreadLocal里面, 这是个线程数据共享的一个类.
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
在这里面就传递了当前的工作线程的信息,并且new了一个message queue,就是消息队列嘛, 用来接收消息的容器.
public static Looper myLooper() {
return sThreadLocal.get();
}
这个函数就返回了上面创建的那个new Looper();
public Handler() {
...
mLooper = Looper.myLooper();
mQueue = mLooper.mQueue;
...
}
在这里就把当前线程的Looper赋给Handler了, 这就发生关系了.
可能有同学还会有疑问, 上面是两个类的不同的语句Looper.myLooper();怎么得到的是同一个呢?
那就分析一下吧;
在Looper类里面有个全局的静态容器
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
再进入ThreadLocal类里面看
public void set(T value) {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
}
values.put(this, value);
}
在这里就把当前的线程的相关信息设进去了.
看看get()函数;
public T get() {
// Optimized for the fast path.
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values != null) {
Object[] table = values.table;
int index = hash & values.mask;
if (this.reference == table[index]) {
return (T) table[index + 1];
}
} else {
values = initializeValues(currentThread);
}
return (T) values.getAfterMiss(this);
}
再这里就返回了当前线程的相关信息.
因为ThreadLocal是个模板容器, 声明为ThreadLocal<T>
在Looper中声明为ThreadLocal<Looper> , 所以 T == Looper .
简单的翻译一下上面的get()和set()吧;
public void set(Looper value) {
values.put(this, value);
}
public void Looper get() {
return values.get(this);
}
这样就很清晰了, 关系就是这么发生的. 回头梳理一下吧.
Looper.prepare()
Looper.myLooper();
xxxHandler = new Handler(){ handleMessage(Message msg){...} };
Looper.loop();
等价于
Looper.prepare() { sThreadLocal.set(currentThread, new Looper(); }
Looper.myLooper() { sThreadLocal.get(currentThread) }
new Handle(){
...
mLooper = sThreadLocal.get(currentThread);
mQueue = mLooper.mQueue;
...}
关系发生了,这时候就可以通过Message进行通信了, 这就不多说了.