The App process is incubated by the Zygote process. First create Looper, looper.prepareLooper (), then create ActivityThread object by calling main in ActivityThread. Initialize. Use the getService function of ActivityManager. Java to obtain ActivityManagerService and use the attachApplication function to initialize the Service. Execution continues with a call to attachApplicationLocked. We then enter the looper.loop () function in main for the message loop.

Looper. The Looper function in Java is the core of app operation

public static void loop() {
Copy the code

Find the Looper you created earlier

final Looper me = myLooper();
Copy the code

All the work is done around the Looper. If the Looper is empty, the application will not run. It is the heart of the loop.

final MessageQueue queue = me.mQueue;
Copy the code

The message queues in the loop are members of Looper

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

In an infinite loop, all messages to be processed are sent to the message queue and then retrieved. It should be noted that if there is no message, it will block here, because it is Linux underlying blocking, the CPU will sleep, and this will not affect the main thread execution. As soon as a message arrives, activate it for message processing.

if (observer ! = null) { token = observer.messageDispatchStarting(); } long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid); try { msg.target.dispatchMessage(msg); if (observer ! = null) { observer.messageDispatched(token, msg); } dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0; } catch (Exception exception) { if (observer ! = null) { observer.dispatchingThrewException(token, msg, exception); } throw exception; } finally { ThreadLocalWorkSource.restore(origWorkSource); if (traceTag ! = 0) { Trace.traceEnd(traceTag); }}Copy the code

This is message handling, and if there is no catch in the execution, an exception will be thrown and the application will hang.

If you don’t want your Application to die, it’s best to add Handler handling to your Application

Handler(Looper.getMainLooper()).post {
    while (true) {
        try {
            Looper.loop()
        } catch (e: Throwable) {

        }
    }
}
Copy the code

This will go into a separate Looper.loop again, they are a Looper, and because of this loop, the application will not be forced to close but at this point, the application is not in a normal state, you can do a few checks, log save, if not, the application has an error, you should exit the application.

Let’s talk about Handler, which is used for all message delivery.

msg.target.dispatchMessage(msg);
Copy the code

The target in the message is a Handler, and the dispatchMessage function is an entry point to the unified processing of the message.

public void dispatchMessage(@NonNull Message msg) { if (msg.callback ! = null) { handleCallback(msg); } else { if (mCallback ! = null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}Copy the code

The callback can be wrapped in Messsge, and when the Handler is created in the main thread, the main queue is assigned to it and messages are sent to the message queue using the following function.

public final boolean postAtFrontOfQueue(@NonNull Runnable r) {
Copy the code
public final boolean post(@NonNull Runnable r) {
Copy the code
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
Copy the code
public final boolean postDelayed(Runnable r, int what, long delayMillis) {
Copy the code
public final boolean sendEmptyMessage(int what)
Copy the code
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Copy the code
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Copy the code
public final boolean sendMessage(@NonNull Message msg) {
Copy the code
public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
Copy the code
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
Copy the code
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
Copy the code

You can also combine handlerThreads by creating your own Handler on child threads

HandlerThread handlerThread = new HandlerThread("work");
handlerThread.run();

Hanlder hanlder = new Hanlder(handlerThread.getLooper());
Copy the code

You can also override Handler to subclass it

private static class InnerHandler extends Handler {
    public InnerHandler(@NonNull Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(@NonNull Message msg) {
    }
}
Copy the code

Or you could write it this way

Handler handler = new InnerHandler(Looper.getMainLooper(), new Handler.Callback() { @Override public boolean handleMessage(@NonNull Message msg) { return false; }});Copy the code

Here is a Callback, and if false is returned here, you can handle both handleMessage messages and code accordingly.

Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
        new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
Copy the code

Send it to itself via the Handler above.