一个线程是否只有一个Looper?
创建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));
}
复制代码
UI线程开始执行时,会执行Looper.prepareMainLooper(),创建mainLooper。创建完成后,接着会执行Looper.loop()。loop()方法会无限轮询消息队列。
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
复制代码
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));
}
复制代码
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
复制代码
handler的常用法
Handler myHandker = new Handler(){
private void handleMessage(Message msg){
...
}
}
复制代码
看下 handler的构造函数
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
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;
}
复制代码
handler中有一个mLooper,前面说了,界面启动时,已经创建了一个mainLooper,mainLooper中包含一个消息队列,和对主线程的引用。 这里通过Looper.myLooper()方法得到mainLooper。我们是在主线程new出来的Handler,主线程中的sThreadLocal已经存在,get()拿到的就是mainLooper。
//静态方法
public static Looper myLooper() {
return sThreadLocal.get();
}
复制代码
handler中的mQueue也就是Looper中的消息队列。
//给handler发送消息
Message msg = new Message();
msg.whta = 1;
myHandler.sendMessage(msg);
复制代码
sendMessage最终会调用sendMessageAtTime
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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//注意这里,message中target就是handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//将这条msg插入了MainLooper中的消息队列中
//此注释可在下面流程看完之后,再看。这的消息队列其实是Looper中的消
//息队列对象,也就是说在非U线程向在U线程创建的HandlerUI发送了一条
//消息后,HandlerUI把消息插入到mainLooper中的消息队列里(最终被创
//建HandlerUI时重写的handleMessage处理。即非UI线程更新UI的原理
return queue.enqueueMessage(msg, uptimeMillis);
}
复制代码
再看MessageQueue,消息队列是用链表结构,通过enqueueMessage方法插入Message,和next()方法取出message。
//将消息插入头部
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
复制代码
Looper是会无限轮询MessageQueue,有消息(mQueue.next()取出),就丢给handler处理。
public static void loop() {
//这里是mainLooper(新开线程中新new出的handler/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;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
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
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
//只要有消息,则由handler的dispatchMessage处理
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
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();
}
}
复制代码
再看handler的dispatchMessage
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//在创建handler的时候,会重写此方法,作相应逻辑处理
handleMessage(msg);
}
}
复制代码
主线程不用执行Looper的prepare()和loop()方法。但是新开线程的话必须手动执行两个方法
new Thread(new Runnable(){
@Override
public void run(){
Looper.prepare();
Handler handler = new Handler();
Looper.loop();
}
}).start();
复制代码
线程和Looper怎么联系起来的呢?
Thread 类中有一个ThreadLocal.Values localValues对象。 回头看Looper.prepare()源码中,有一句
sThreadLocal.set(new Looper(quitAllowed));
复制代码
ThreadLocal中的set方法
//在执行Looper.prepare()的线程A中,将
public void set(T value) {
//下面两句是获取线程A中的 localValues对象。
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
}
//将创建的Looper中的ThreadLocal<Looper>对象sThreadLocal作为key,
//looper为value,存入ThreadLocal.Values中,
//这样就可以通过sThreadLocal.get()获取到对应的Looper,参见Looper中
//的myLooper()方法
values.put(this, value);
}
复制代码
/**
* Gets Values instance for this thread and variable type.
*/
Values values(Thread current) {
return current.localValues;
}
复制代码
Looper中的myLooper()方法
public static Looper myLooper() {
return sThreadLocal.get();
}
复制代码
ThreadLocal中个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);
}
复制代码