为了账号安全,请及时绑定邮箱和手机立即绑定

MessageQueue中死循环轮询messeag没发生ANR的原因猜想。

messageQueue轮询消息是否存在及要传递给的target对象时,为什么没发生ANR:个人猜想,当不存在在消息时,发生了循环阻塞,就像在socket编程中,当没有客户端访问时,服务器端就阻塞在accept()方法中,当有消息需要处理时:循环继续运行,不知道对不对。

正在回答

4 回答


    /**

     * Run the message queue in this thread. Be sure to call

     * {@link #quit()} to end the loop.

     */

    public static void loop() {

        Looper me = myLooper();

        if (me == null) {

            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");

        }

        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 (msg != null) {

                if (msg.target == null) {

                    // No target is a magic identifier for the quit message.

                    return;

                }


                long wallStart = 0;

                long threadStart = 0;


                // 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);

                    wallStart = SystemClock.currentTimeMicro();

                    threadStart = SystemClock.currentThreadTimeMicro();

                }


                msg.target.dispatchMessage(msg);


                if (logging != null) {

                    long wallTime = SystemClock.currentTimeMicro() - wallStart;

                    long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;


                    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);

                    if (logging instanceof Profiler) {

                        ((Profiler) logging).profile(msg, wallStart, wallTime,

                                threadStart, threadTime);

                    }

                }


                // 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.recycle();

            }

        }

    }


0 回复 有任何疑惑可以回复我~
    /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the 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.recycle();
        }
    }


0 回复 有任何疑惑可以回复我~

Looper不断轮询MessageQueue,当取出msg时就会执行,如果该msg执行时间过长就会发生ANR。

1 回复 有任何疑惑可以回复我~

不错,我也是这样想的。如果发生阻塞,就会等待资源,进程实体有三个状态,就绪,阻塞,执行。阻塞状态就是等待资源

1 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消
Android面试常客Handler详解
  • 参与学习       54881    人
  • 解答问题       183    个

学Android开发,必学Handler,也是Android面试常客

进入课程

MessageQueue中死循环轮询messeag没发生ANR的原因猜想。

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信