其实Looper
的源码比较短,看起来还是比较容易的。
首先是构造方法。不过私有化了。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
通过构造方法可以清晰的见到,这里创建了一个很重要的对象,也就是MessageQueue
对象。然后对于调用者,创建Looper
对象的方法其实是prepare()
方法。
public static void prepare() {
prepare(true);
}
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));
}
这个方法也是很简单的,创建了一个Looper
对象,并放入了sThreadLocal
中。ThreadLocal
可以先简单理解成一个容器。那么如果要获取之前创建的Looper
对象,调用的是myLooper()
方法。
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
结合这两个方法可以看出,如果要使用自己创建Looper
对象。那么步骤是先调用prepare()
,再调用myLooper()
。
/**
* Initialize the current thread as a looper, marking it as an
* application's main looper. The main looper for your application
* is created by the Android environment, so you should never need
* to call this function yourself. See also: {@link #prepare()}
*/
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
/**
* Returns the application's main looper, which lives in the main thread of the application.
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
对于主线程的Looper
对象获取,可以通过getMainLooper()
方法获取。但是其实和自己创建并获取的逻辑还是一样的。依然是通过prepare()
方法去构造了一个Looper
对象。最终取出来也是通过ThreadLocal#get()
的方式去获取的。
然而,Looper
有一个重要的方法,叫loop()
。该方法其实是一个死循环。
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
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;
// 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;
}
try {
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
msg.recycleUnchecked();
}
}
我去掉了里面log
相关的代码。这里面其实逻辑也很简单,就是通过死循环,不断的去获取MessageQueue
里面的Message
对象,然后调用msg.target.dispatchMessage(msg);
【这里的msg.target
是一个Handler
对象。】
所以,一般我们在重新Handler
的时候,都会重写 handlerMessage()
方法,其实重写dispatchMessage()
也是一样的。这个看一下Handler#dispatchMessage()
就明白了。
// Handler.java
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
不过,如果你执行骚操作,两个都重写。那么两个都会收到回调。如果你再执行骚操作,两个都重写,但是去掉了 dispatchMessage()
里面的super.disptachMessage()
,那么handlerMessage()
就会失效,只有dispatchMessage()
会生效。
// MyActivity.java
private Handler mainHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
Log.d(TAG, "handlerMessage==" + msg.what); // 2. 收不到回调了
}
@Override
public void dispatchMessage(Message msg) {
// super.dispatchMessage(msg); // 1. 注释了 super, 会导致 hanlderMessage() 不被调用
Log.d(TAG, "dispatchMessage==" + msg.what); // 这里肯定能收到回调
}
};