其实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); // 这里肯定能收到回调
}
};
博客围绕某源码展开,介绍了其构造方法私有化,创建重要对象并放入容器。说明了使用自己创建对象的步骤,以及主线程对象获取逻辑。还提到重要方法是死循环,不断获取对象并调用。同时指出重写相关方法的不同情况及效果。
3311

被折叠的 条评论
为什么被折叠?



