结论:一个线程可以有多个Handler,只有一个Looper,只有一个MessageQueue。多个Handler共用一个Looper和一个MessageQueue。一个应用中可以有多个Handler,多个Looper,多个MessageQueue。
- 一个线程可以有多个Handler
这个很好理解,你在Activity中,new 多少个Handler都不会出问题,而且每个Handler都有sendMessage
2.假如一个线程可以有多个Looper
大家都知道UI线程系统会默认帮我们创建一个Looper对象,这样每次我们创建Handler时候,就不用自己去调用Looper.prepare(),Looper.loop()方法。如果多个Looper可以在一个线程中,那么应用完全只可以自己创建一个Looper,这样加上系统创建的,就会有两个Looper对象。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Looper.prepare();
mHandler = new Handler(mThread.getLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
}
上述代码运行会出现RuntimeException
已经说得很明白,每个线程只能有一个Looper对象。
查看源码:
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
先从sThreadLocal中获取,如果获取到了,说明已经存在对应的Looper对象,直接抛异常。没有则创建新的Looper,然后存到sThreadLocal中。
- 一个线程只有一个MessageQueue
这个要从源码的角度看,Handler两个主要的构造方法
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public Handler(Callback callback, boolean async) {
. . .
mLooper = Looper.myLooper();
. . .
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
可以看到mQueue 是从对应的Looper对象中获取到的。上面已经说明一个线程只能有一个Looper存在,那么MessageQueue也只能有一个。所有的Handler共用Looper和MessageQueue。
如果多个Handler共用一个MessageQueue,那么Looper如何知道将这个Message发送到哪个Handler呢?
public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
public Object obj;
...
/*package*/ Handler target;
在Message中都会有一个Handler对象,叫做target,也就是发送该Mesaage的Handler对象,所以不同的Message里面的tartget可能是不用的,所以Looper轮训到这个Message后,就可以根据这个tartget进行分发处理。
常用的发送消息方式:
mHandler.sendEmptyMessage(0);
mHandler.sendEmptyMessageDelayed(0,1000);
其实sendEmptyMessage也调用的sendEmptyMessageDelayed
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
创建一个Message,然后将我们传递的what设置到对应的Message上
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
如果传递的时间小于0那么设置为0,如果大于0,获取系统时间 + 上要 延迟的时间。
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
如果没有MessageQueue,会报错,然后将Message放入队列
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//关键一步,Message持有当前Handler的引用
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
Message msg = new Message();
mHandler.sendMessage(msg);
Message msg = Message.obtain();
mHandler.sendMessage(msg);
直接new一个Message发送,也会调用sendMessageDelayed,最终Message也会持有当前Handler的引用。
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
只要你使用sendMessageXXX,Handler都会在Message上将自己设置为target。
看一下Looper轮询消息,是如何处理的:
public static void loop() {
final Looper me = myLooper();获取到Looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;获取到MessageQueue
......
for (;;) {
Message msg = queue.next(); // 循环获取nextMessage
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
.......
try {
msg.target.dispatchMessage(msg);发送给对应的target(Handler)的dispathMessage方法
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
}
....
msg.recycleUnchecked();回收对应的Mesaage
}
}
Handler 的dispathMessage,调用自己的handleMessage方法
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
回收Message
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
Handler的handleMessage是运行在主线程还是子线程,是谁决定的?答案是Looper
在主线程中,系统默认帮我们创建了Looper,在子线程中,我们也可以创建自己的Looper,创建的方式就是调用Looper.prepare();
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//首先获取,如果对应的Looper存在,抛异常,一个线程只能有一个Looper
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
如果没有,创建并存入sThreadLocal中,
sThreadLocal.set(new Looper(quitAllowed));
}
在创建Looper的时候,创建了该Looper对应的MessageQueue
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
所以说,当你在主线程调用prepare时,你的handleMessage运行在主线程,如果你是在子线程中调用的prepare,那么你的handleMessage方法,是运行在子线程中的。也就是说你的Looper是在哪个线程创建的,你的handleMessage就是在哪个线程执行。