我想知道Looper类如何在Looper附加的Thread中实际处理Runnables(通过Handler类)?如果一个looper循环遍历其messageQueue,那么肯定会是该线程的阻塞操作?我想它本身必须执行一些线程技巧,但是它如何将发布的Runnables run()方法添加到主机线程堆栈上?
很多问题!任何帮助将非常感激。谢谢!
编辑:
通过Looper class file类我看到下面的内容,这让我更加困惑,因为所有注释都指的是在主线程中运行的looper,而且还在等待MessageQueue上的新消息时进行阻塞操作。这怎么不阻塞UI /主线程???
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static final void loop() {
Looper me = myLooper();
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();
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.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("Looper", "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.recycle();
}
}
}
/**
* Returns the application's main looper, which lives in the main thread of the application.
*/
public synchronized static final Looper getMainLooper() {
return mMainLooper;
}
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
// sThreadLocal.get() will return null unless you've called prepare().
private static final ThreadLocal sThreadLocal = new ThreadLocal();
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
答案 0 :(得分:2)
你是对的。构造Looper.start()的原始线程被调用成为所有发布Runnables和Messages的线程。 确实意味着该线程被阻止。
答案 1 :(得分:0)
好的,看看Stack我找到了另一个回答我的问题。我的主要困惑来自于this post没有意识到以下情况。除了发布到处理程序的东西(并添加到Loopers MessageQueue)之外,我错误地想到了一切都是在线性调用堆栈中执行的,但考虑到这一点,这更有可能是如何实现任何带有UI的程序,并且更多的感觉是,UI线程上的每个东西都源自Looper,并且此线程上的所有执行路径都将返回到它!感谢Berdon试图回答我的问题,我确定我没有充分解释我的问题:)
关于android UI线程:在某些时候(可能在任何之前) 创建了活动等)框架已经建立了一个Looper (包含MessageQueue)并启动它。从这一点开始, UI线程上发生的一切都是通过该循环。这个 包括活动生命周期管理等。所有回调你 override(onCreate(),onDestroy()...)至少是间接的 从该循环调度。你可以在堆栈中看到它 跟踪异常。 (你可以尝试一下,只需写入一个a = 1/0; 在onCreate()的某个地方...)