现在的位置: 首页 > 综合 > 正文

Looper与Handler是如何通过Message发生关系的

2013年12月09日 ⁄ 综合 ⁄ 共 2274字 ⁄ 字号 评论关闭

经常看到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进行通信了, 这就不多说了.
from : http://www.2cto.com/kf/201212/177537.html

抱歉!评论已关闭.