Looper作为引擎般的存在,主要作用是维持一个死循环,一旦有消息到来就通知handler分发事件。
Looper的创建
//线程中初始化 获取Looper
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//sThreadLocal 存放线程的局部变量 每个线程拿到一个原始变量的副本进行操作
//在这里就是为每个线程存放一个Looper对象,如果已经存在 则报异常
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//sThreadLocal 存放线程的局部变量 每个线程拿到一个原始变量的副本进行操作
//多了一个quitAllowed 默认是true 主线程赋值false表示looper不可退出
sThreadLocal.set(new Looper(quitAllowed));
}
//主线程初始化Looper的地方 在MainThread的main方法里面调用 这也是主线程里面不用调prepare的原因
public static void prepareMainLooper() {
prepare(false);
//下面是主线程多出来的部分 就是单独的为主线程的Looper设置一个线程局部变量sMainLooper
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//myLooper() 方法里就一句话 return sThreadLocal.get(); 最终拿到线程sThreadLocal
sMainLooper = myLooper();
}
}
....
//上面 进过prepare 最终new一个Looper对象
//同时拿到MessageQueue和创建宿主线程thread;
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Looper的退出
public void quit() {
mQueue.quit(false);
}
public void quitSafely() {
mQueue.quit(true);
}
上面简短的代码可以看出 其调用的是成员变量MessageQueue的退出方法 那我们就跟进看一看
MessageQueue中的代码
void quit(boolean safe) {
//mQuitAllowed 主线程调用prepare时传false 不允许在主线程中退出循环
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
//safe looper中传入判断是否安全退出
//安全退出则只移除等待传递的消息否则清空所有
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previously false.
nativeWake(mPtr);
}
}
Looper运作
核心部分
public static void loop() {
//拿到Looper对象
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;
//重置并获取当前线程跟踪令牌 确保线程身份不变
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
//looper维持的无限循环
for (;;) {
// 消息出队 获取消息
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
//拿到消息后进行消息分发
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
//事件分发后判断线程身分是否有变
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
//消息处理完成后标记为已使用 扔回回收池中 并清空消息的属性变量等信息
msg.recycleUnchecked();
}
}
消息如何出队 下一篇会说下MessageQueue和message