Handler学习(未完)
Handler, MessageQueue, Looper
Handler:
- 外界通过handler发送Message,handler将Message放入MessageQueue中
- Handler收到looper调用处理Message的方法,根据消息内容做相应处理(dispatchMessage)。调用的位置决定了处理消息位于哪个线程。
MessageQueue:
存放Message的队列
Looper:
循环从MessageQueue中取出message,调用Message中的Target的diapatch方法实现消磁处理(即Handler)源码解析
Message结构本身是一个数据链表。
Looper的作用就是从消息队列中取消息交给handler去处理。
looper是一个线程一个的,Looper类可以认为是一个单例模式,只不过有几点特殊:(1)不是传统的static持有自己对象,而额外加了ThreadLocal
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
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));
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
private static Looper sMainLooper; // guarded by Looper.class
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
loop方法的loop方法应该是决定handler处理消息的所在线程。但是因为loop对象本身就是属于所在线程的变量,因此loop的执行也只会在当前线程中(别的线程中不存在它),也就是创建Looper的地方。loop方法在最开始的时候会去获取一下当前线程looper,从这个looper中取queue,queue中的元素是message,handler又是message的成员变量,这样就决定了不管在那个线程给handler发送消息,都不会影响改变线程,因为handler只负责向在创建时已经决定好的特定线程的looper的queue中放入message。
如果在一个线程中创建,在另一个线程中调用loop,会直接报looper不存在异常,或就执行另一个线程的loop方法,而这个线程中的message不包含要用来处理消息的handler,handler对应的loop仍然不会开始执行,向handler中发送消息没有用。(虽然会去wake,不确定逻辑,到native方法层了)
handler在创建的时候一定要有looper,即使不在创建的时候传入looper,默认的构造方法也要用Looper去获取当前线程的looper,因此除非是主线程,在创建的时候一定要prepare,否则会直接报异常。
public Handler(Callback callback, boolean async) {
...
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
向handler发送消息: 也就是向queue中存入message,等着looper取到执行。
handler处理消息: looper调用handler的diapatchMessage方法。处理的方式对应着创建handler时决定好的处理消息的方式。有三种: CallBack handler.post(new Runnable), 和 handler的handlemessage
- handler.post(new Runnable)会取一个message然后将传入的runnalbe赋给meg的callback
- CallBack会创建为Handler的私有变量Callback
- handler的handlemessage是一个空方法
三者执行的优先级为:优先执行msg的callback,如果为空;执行创建handler时的callback,最后调用handlerMessage方法。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
移除所有消息 removeMessages和removeCallbacksAndMessages都是用来移除消息的,移除特定消息或移除所有消息。 退出loop 退出loop有两个方法,调用loop的quit方法和quitSafe方法,区别就是safe方法等到队列中的任务执行完才退出。
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
* 循环* 整个过程中会涉及两个循环,一个是loop的循环,只要开启了会一直等待去处理消息,直到拿不到消息。一个是messagequeue中的next方法拿下一个消息,会一直循环知道拿到消息或者quit。
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
...
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...
}
}
Message next() {
...
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
...
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
msg.markInUse();
return msg;
}
} else {
nextPollTimeoutMillis = -1;
}
if (mQuitting) {
dispose();
return null;
}
...
...
}
}
** 注释
ThreadLocal是线程局部变量的类,为每个使用该变量的线程提供独立的变量副本。