1.判断方法
可以借助Looper
来判断当前线程是否是主线程:
代码:
public boolean isMainThread() {
return Looper.getMainLooper() == Looper.myLooper();
}
getMainLooper()
得到的是整个application的主线程。myLooper()
得到的是当前线程。
2.Looper
官方文档里说明:
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
官方推荐使用例子:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
2.1.Looper中变量声明
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;
private Printer mLogging;
private long mTraceTag;
sThreadLocal
每个使用该变量的线程都会将已创建的Looper存储到其中,并在prepare
的时候调用判断,是否已经创建过Looper
2.2.prepare
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {//每个线程只能有一个looper
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
2.3.构造方法
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
创建了消息队列并绑定了当前线程
2.4.loop方法
public static void loop() {
final Looper me = myLooper(); //返回当前线程绑定的looper
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
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);
}
// 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();
}
}
首先调用myLooper
方法获取当前looper:
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
接着拿到该looper对应的消息队列me.mQueue
。然后就无限循环从队列里取消息Message
,取到消息后就调用msg.target.dispatchMessage(msg)
方法进行消息处理。
消息处理完之后要进行回收,msg.recycleUnchecked()
3.总结
一个线程对应一个Looper,一个Looper对应一个MessageQueue,Looper调用loop()开始通过消息队列的next()
方法来无限循环获取消息并处理。