public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
先来个Handler执行过程的总结:
1、 Looper.prepare()方法
为当前线程绑定looper,
在looper构造方法中创建一个messageQueue
2、 创建handler 重并写handleMessage方法
3、 使用handler发送消息,最终消息都会发送至messageQueue对象中,在messageQueue当中,所有的message按应该执行的时间的先后顺序,从小到大排列
4、Looper.loop()
在此方法中,开启死循环,不断的从messageQueue中取出应该执行的message,并执行message 对应的handler中的dispatchMessage方法,即,执行我们重写的handleMessage方法
参照以上分析在子线程中创建Handler对象:
new Thread(){
@Override
public void run() {
Message msg = Message.obtain();
Looper.prepare();//若没有调用此方法则抛出异常 Can't create handler inside thread that has not called Looper.prepare()
Handler handler2 = new Handler(){
public void handleMessage(Message msg) {
Toast.makeText(MainActivity.this, "收到子线程message消息", 0).show();
};
};
handler2.sendMessage(msg);
Looper.loop();
}
}.start();
对比在主线程中创建Handler实例对象我们发现,在子线程中创建Handler对象需要在创建前调用Looper.prepare()方法在创建后调用Looper.loop方法,那究竟这两个方法是做什么的呢?
先看看系统的Looper.prepare方法:
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 为当前线程绑定一个looper对象,以sThreadLocal为key
sThreadLocal.set(new Looper());
}
即:调用Looper.prepare方法时为当前线程绑定了一个Looper对象,所以Looper.prepare方法只能调用一次,即一个线程只能有一个Looper对象
再看看Looper的构造方法:
private Looper() {
mQueue = new MessageQueue();
}
因为一个线程只能有一个Looper对象,所以一个线程也只能有一个MessageQueue对象
先让我们看看Handler的构造方法:
public Handler() {
//获得当前线程的looper对象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
// 获得looper中MessageQueue的引用
mQueue = mLooper.mQueue;
}
再看看系统的Looper.myLooper方法:即获取调用Looper.prepare方法时保存在sThreadLoad的Looper对象,所以Looper.prepare方法要在new Handler方法前调用
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
即:当创建Handler时会先调用Looper.myLooper()方法获取当前线程的Looper对象,如果Looper==null,则抛出异常
通过以上两个方法,当前线程的唯一Looper对象和MessageQueue对象都已创建,接下来该sendMessage了
查看系统源码可知:sendEmptyMessage等,发送信息的方法,最终都是调用了SendMessageAtTime(msg,when);
而SendMessageAtTime(msg,when);方法最终的目的就是为了queue.enqueueMessage(msg, uptimeMillis);,其中msg为发送的Message对象,uptimeMillis为SystemClock.uptimeMillis() + when
查看系统的enqueueMessage方法,该方法最终实现在messageQueue当中,所有的message按执行的先后顺序,从小到大排列
final boolean enqueueMessage(Message msg, long when) {
msg.when = when; // 将执行时间设置给msg.when
Message p = mMessages; // 定义变量p = mMessage ,mMessage初终指向对列的第一个Message 对象
if (p == null || when == 0 || when < p.when) {
// 当队列中为空的时候,mMessage = msg
msg.next = p;
mMessages = msg;
this.notify();
} else {
// 否则将要进入队列的msg的执行时间和队列中的message的执行时间进行比较,
// 最终会使messageQueue中的所有的message按时间为顺序从小到大排列
// 即按执行的先后顺序排列
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
this.notify();
}
}
消息发送成功这时候该调用Looper.loop方法:即完成了从MessageQueue中取出需要执行的Message,并执行我们重写的handlMessage方法
public static final void loop() {
//获得当前线程的looper对象及messageQueue对象
Looper me = myLooper();
MessageQueue queue = me.mQueue;
//开启while(true)循环
while (true) {
//从消息队列中取出一个message,如果message执行时间不到,那就wait等一会
Message msg = queue.next(); // might block
//执行message 对应的handler中的dispatchMessage方法,即,执行我们重写的handleMessage方法
msg.target.dispatchMessage(msg);
}
}
}