The relevant content of the article has been authorized to “Guo Lin” public account published

preface

Nice to meet you ~ welcome to read my article.

This article is the fifth in a series that summarizes the workflow of the Handler and provides a higher level of understanding of the Handler mechanism.

The Handler series is divided into six parts:

  1. Part 1: Start the series with Handler from 0;
  2. The second part introduces the internal schema of Handler, and elaborates on the key class ThreadLocal.
  3. The third part: parsing Handler internal key classes: Message, MessageQueue, Looper;
  4. Part 4: Handler internal key class: Handler, at the same time introduce HandlerThread;
  5. The fifth part: summarize Handler, think Handler from the perspective of source code design;
  6. Part 6: Handler FAQ;

This is part five of a series of articles. Readers can go to the author’s home page and select the sections they are interested in.

So, let’s get started.

The body of the

The working process

This part is mainly about the overall process, the front scattered about the functions of each component and source code, now on the unified about their overall process. Look at the picture first:

  1. Handler sets up a series of apis that allow developers to send various types of messages using Handler, which eventually calls the enqueueMessage method to join the queue
  2. Call MessageQueue’s enqueueMessage method to insert messages into MessageQueue’s linked list, waiting to be retrieved and processed by Looper
  3. Looper retrieves the Message and calls the Handler corresponding to the Message to process the Message

This finishing process is clear, I will not repeat the details of the source code analysis, if the reader which part is not clear, you can go to the author’s home page to find the corresponding part to look again.

Rethinking the Handler message mechanism

That’s all I have to say about the Handler mechanism. But I wonder if readers have the same question as I do:

Why is the Handler mechanism called the messaging mechanism in Android? Is the Handler really just used to switch threads and update the UI? How to better understand the Handler messaging mechanism from a source code design perspective?

Every time I learn about mechanics in Android, I like to study his role, or ideas, in the design of Android source code. This helps me to take my understanding to another level. This is a brief introduction to my understanding of the Handler mechanism.

Handler mechanism, I think it’s just called Handler because we’re dealing with handlers, so it’s called Handler mechanism, and if we’re dealing with Looper a lot maybe it’s called Looper mechanism. More specifically, it’s Android messaging.

As we know, every Java program has one entry: the main method, from which we enter our application. I believe that every reader has the experience of using C language to write a student management system, how do we stop the program not to end directly? Wait by loop + input. We would write an infinite loop in the outermost layer, and then constantly listen for input and execute commands based on that input. When the user has no input, it waits forever. This is similar to the Handler mechanism. The Handler mechanism uses a multithreaded approach. The main thread waits for messages and then sends messages from other threads for the main thread to execute logic. This is also called transaction-driven design.

Let’s look directly at the Main method of an Android application:

public static void main(String[] args) {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
    AndroidOs.install();
    CloseGuard.setEnabled(false);
    Environment.initForCurrentUser();
 final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());  TrustedCertificateStore.setDefaultUserDirectory(configDir);  Process.setArgV0("<pre-initialized>");  // Initialize Looper  Looper.prepareMainLooper();  long startSeq = 0;  if(args ! =null) {  for (int i = args.length - 1; i >= 0; --i) {  if(args[i] ! =null && args[i].startsWith(PROC_START_SEQ_IDENT)) {  startSeq = Long.parseLong(  args[i].substring(PROC_START_SEQ_IDENT.length()));  }  }  }  / / create ActivityThread  ActivityThread thread = new ActivityThread();  thread.attach(false, startSeq);  if (sMainThreadHandler == null) {  sMainThreadHandler = thread.getHandler();  }  if (false) {  Looper.myLooper().setMessageLogging(new  LogPrinter(Log.DEBUG, "ActivityThread"));  }  Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  / / start the stars  Looper.loop();  throw new RuntimeException("Main thread loop unexpectedly exited"); } Copy the code

However, we can see that there is not much code in the Activity. After activating ActivityThread and Looper, no other logic is executed. How does our Activity get called and execute logic? Through the Handler. Android is transaction-driven, with transactions constantly being distributed to make the entire application run. Those familiar with the Activity startup process will recall that AMS communicates with the application through the Binder mechanism, which then sends a message to the main thread, which then executes the corresponding logic. Their relationship can be represented by the following graph:

When the application process is created, only Looper and handler for the main thread, as well as other binder threads, are created. The AMS then communicates with the application through Binder, sending messages to the main thread to enable the application to perform actions such as creating activities. Instead of writing logic for endless loops and waiting for user input, the application can run and never end. I won’t go into details about how to start an Activity here, but you can refer to another article by the author (detailed explanation of the process of starting an Activity). The application then opens another thread to receive the user’s touch input and so on, wrapping it as a message and sending it to the main thread to update the UI.

It can be said that “no message, no Android”, the entire Android application is based on this message mechanism to run. It’s not just about switching threads, it’s about the whole foundation of android applications.

The last

This series of articles starts with a primer, goes into depth on the source code and functions of each class, and finally takes a look at the overall messaging design idea. Readers are already familiar with the Handler messaging mechanism.

We don’t use messaging very much on a daily basis, and while it’s very important, we use it mostly when users switch threads to update the UI. There are many mature and very convenient frameworks to use: RxJava, Kotlin coroutines, and so on. But because the Handler mechanism for Android programs is really very important, for in-depth learning android is still very necessary to learn, to understand.

So that’s all we have to say about Handler in general. Hey, synchronization barriers, where’s IdleHandler? Why not? This is the part that goes into the final part, which is the next part. Answer some key questions about handlers, including IdleHandler and synchronization barriers.

Hope this article is helpful.

Full text here, the original is not easy, feel help can like collection comments forward. I have no talent, any ideas welcome to comment area exchange correction. If need to reprint please private communication.

And welcome to my blog: Portal

This article is formatted using MDNICE