gpt4 book ai didi

Android Looper 和调用栈

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:08:00 33 4
gpt4 key购买 nike

我想知道 Looper 类实际上是如何处理 Looper 附加到的 Thread 中的 Runnables(通过 Handler 类)的?如果一个 looper 在它的 messageQueue 中循环,那么它肯定是那个线程的阻塞操作?我想它本身一定在执行一些线程技巧,但它如何将发布的 Runnables run() 方法添加到主机线程堆栈中?

很多问题!任何帮助将非常感激。谢谢!

编辑:

通过 Looper 查看 class file我看到下面的类,这让我更加困惑,因为所有评论都提到了在主线程中运行的循环程序,而且它在等待 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());
}

最佳答案

你完全正确。调用构造 Looper.start() 的原始线程成为处理所有已发布的 Runnable 和消息的线程。这确实意味着这个线程被阻塞了。

关于Android Looper 和调用栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6984263/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com