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.