最近阅读深入理解android内核设计思想这本书,第一次接触android内核源码,看着是既枯燥又枯燥,当然看源码要从ui主线程看起,这里剖析下ActivityThread中looper、handler、message在里面的关系。
可以看到这里和普通线程循环读取消息序列不同:
1、普通线程使用prepare()就行了,主线程使用的是premMainlooper();
2、普通线程会在中间创建一个帮的looper的handler对象,而主线程会从当前线程获取到主线程的handler(gethandler)。
针对1,打开premainlooper源码:
打开prepare()源码
———————————–
第二步当然是绑定与Thread绑定的handler了
这里调用getHander方法,获得handler,
ok
这里会先获取到looper对象的消息队列messagequeue,然后进入死循环for(;;),不断的.next获取到最前的msg,然后进入关键一步msg.target.dispatchMessage(msg);打开这里的target就是执行消息队列任务的handler,而dispatchMessage进入源码看下是什么:
这里在source insight进入ActivityThread的void main方法中:
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
可以看到这里和普通线程循环读取消息序列不同:
1、普通线程使用prepare()就行了,主线程使用的是premMainlooper();
2、普通线程会在中间创建一个帮的looper的handler对象,而主线程会从当前线程获取到主线程的handler(gethandler)。
针对1,打开premainlooper源码:
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
这里可以看出premainlooper和调用了prepare方法,参数false表示不允许退出,经过prepare后mylooper会得到一个与本地线程的looper对象,然后赋值给sMainLooper对象,所以主线程的looper和其他码农手写的looper没有本质区别的。
打开prepare()源码
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));
}
<\code>
<code lang="java">
public static Looper myLooper() {
return sThreadLocal.get();
}
总结:可以看到prepare()方法为当前线程sThreadLocal生成了一个looper,即myLooper,然后preparemainlooper中再让sMainLooper指向myLooper即指向当前线程的Looper对象,到这里,ui主线程中looper的创建工作完成。
———————————–
第二步当然是绑定与Thread绑定的handler了
这里调用getHander方法,获得handler,
mH是一个H对象
1 |
private
class H
extends Handler
|
ok 明白H是个Handler对象就行了,sMainThreadHandler会一直从当前线程通过getHandler方法获得handler对象,然后进入下一步,最关键的异步.loop()方法。
——————————————-
进入Looper.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;
}
// 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();
}
}
ok
这里会先获取到looper对象的消息队列messagequeue,然后进入死循环for(;;),不断的.next获取到最前的msg,然后进入关键一步msg.target.dispatchMessage(msg);打开这里的target就是执行消息队列任务的handler,而dispatchMessage进入源码看下是什么:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
这里会执行一个handlemessage方法,这也是为什么在我们通过创建一个handler时为什么要重写handlemessage的原因,而且我们还要手动的通过handler的sendmessage方法发送一个消息。
———————————————
到此ActivityThread中消息循环机制完成,总结下:
1、prepareMainLooper 进行消息队列的创建,生成looper对象,且让sMainLooper指向它
2、通过gethandler获取当前线程handler,指向一个H对象
3、进入Looper死循环不断地获取消息并且让handlemessge去处理。
这和普通线程在本质上是完全一样的。
———-
纯手打,转载请注明出处