Handler,Looper,Message
2019-12-24 本文已影响0人
JackyWu15
从《App的启动过程》一篇知道,zygote会fork新进程,然后加载ActivityThread类,并调用其main方法,这里即为应用程序的启动入口。
public final class ActivityThread {
......
//zygote孵化新进程后,加载ActivityThread,并调用main方法
public static void main(String[] args) {
......
//创建UI线程的Looper,也即主线线程的Looper,每个MessageQueue只会属于一个线程,而 MessageQueue在Looper中
Looper.prepareMainLooper();
//生成ActivityThread对象
ActivityThread thread = new ActivityThread();
//false表示非系统应用调用,这里是创建Application和Activity,以及Instrumentation的入口
thread.attach(false);
//获取Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
......
//启动UI线程消息循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
//创建并Looper,并赋值给sMainLooper引用
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
//通过ThreadLocal获取Looper,ThreadLocal保证每个线程有一份自己的Looper
public static Looper myLooper() {
return sThreadLocal.get();
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//创建Looper
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
//消息队列
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public final class Looper {
private static final String TAG = "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;
//循环消息队列
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;
// 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);
}
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是通过Looper的ThreadLoadcal来获得Looper,进而获得MessageQueue的。Looper创建时保存了当前的线程,用于标记一个线程一个Looper,而当前Looper又会被ThreadLoadcal保存下来
new Thread( new Runnable() {
@Override
public void run() {
Looper.prepare();
Handler handler = new Handler();
handler.post( new Runnable() {
@Override
public void run() {
}
} );
Looper.loop();
}
} ).start();