Why doesn't the Looper infinite loop in the Handler cause the application to freeze?

First, let’s list the general situations of ANR:
1. Keyboard input event, touch no response for 5s;
2. Receiver broadcast receiver 10s timeout and no response;
3. Service service 20s timeout and no response;
...

Let me briefly introduce

Handler will start in the main method of ActivityThread after the application starts:

public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        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());

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

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

Here we can see three key lines:
Looper.prepareMainLooper();

...
if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
}

...
Looper.loop(); //loop

The loop method in Looper will take out the message from the next method in MessageQueue

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;
        
        ...

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
			...

            msg.recycleUnchecked();
        }
}

Message msg = queue.next(); // might block

The next method will call the native method  nativePollOnce ,

Message next() {
      
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);

            ...
        }
}

When there is no message in the MessageQueue , queue.next() will be blocked in the nativePollOnce() method. When nativePollOnce() is blocked, the main thread will release CPU resources and enter a dormant state.
Until a new Message is obtained , the main thread will be woken up to continue working.

There is a difference between the main thread going to sleep and an infinite loop here:

The sleep state means that in the kernel state, the main thread is suspended, and the thread state is transferred to the sleep state.

Infinite loop refers to stuck execution of a time-consuming operation in the main thread, loop() will always process a message, and there are many messages in the for loop that need to be processed, and this message takes a long time to process, this message The processing time will turn into no response to other click events, thus triggering ANR.

 

 

Guess you like

Origin blog.csdn.net/qq_33539839/article/details/113478496