Android Looper和调用堆栈

时间:2011-08-08 15:10:30

标签: android multithreading

我想知道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());
    }

2 个答案:

答案 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()的某个地方...)