This is the first article in the “Android messaging” series, which is listed below:

  1. You must have eaten sushi! — Android messaging mechanism (construction)
  2. You must have eaten sushi! — Android Messaging (distribution)
  3. You must have eaten sushi! — Android messaging (processing)

The story of the messaging mechanism

Sushi Chen is placed on sushi plates, which are lined up on a conveyor belt in sequence. After the conveyor belt is activated, the sushi is presented to you one by one, and you have three ways to enjoy it.

Bringing Android concepts in, it becomes the story of Android messaging:

  • Sushi dishes — – >Message
  • The queue – >MessageQueue (MessageQueue)
  • Conveyor belt — – >Message pump (Looper)
  • Sushi –> Data you care about
  • How to enjoy sushi –> How to process data

Temporarily not foundHandlerThe corresponding entity in this scenario. It’s a more abstract concept that produces sushi, sends it to the conveyor belt, and defines how to eat it. Let’s call it thetaMessage handler.

If you want to open your own revolving sushi restaurant, the following questions are key:

  1. How to produce sushi (how to structure messages)
  2. How to Distribute sushi (How to distribute messages)

With these two questions in mind, let’s analyze the message mechanism source code. (PS: the bold italics in the following words represent the inner play to guide the source code reading)

How to structure messages

The sushi plate is reused. After the sushi is eaten, it is cleaned and then stored for reuse. No boss destroys sushi dishes after a meal. It’s too expensive to buy new ones. Similarly, constructing a message object is expensive. Is it reusable like a sushi plate? If so, where is it stored? Let’s start with handler.obtainMessage () :

public class Handler { ... public final Message obtainMessage(){ return Message.obtain(this); }... } public final class Message implements Parcelable { ... /** * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned. * @param h Handler to assign to the returned Message object's <em>target</em> member. * @return A Message object from the global pool. */ public static Message obtain(Handler h) { Message m = obtain(); m.target = h; return m; }... }Copy the code
  • Among themMessage.targetIs aHandlerType of a member variable.Why does Message record the Handler object from which it was constructed?Good question! But the answer to that question will have to wait for analysisMessage processingI’ll leave you in suspense.
  • The endpoint of constructing the message invocation chain isMessage.obtain(), the source code is as follows:
Public final class Message implements Parcelable {// // Sometimes we store linked lists of these things /*package*/ Message next; Private static Message sPool; private static Message sPool; Private static int sPoolSize = 0; . /** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { if (sPool ! = null) {//1. Define a reference to the header of the Message chain: Message m = sPool; //2. Define the new message chain header sPool = m.next; //3. Break chain m.ext = null; m.flags = 0; // clear in-use flag sPoolSize--; Return m; Return new Message(); }... }Copy the code
  • If the data structure inThe listAnd the reflection,obtain()You’re taking the head of the list. The illustration is as follows:

  • Message pooling is implemented using a linked list structure. That Message must have a “pointer” to a subsequent node, and sure enough, find Message Next in its member variable; .

  • The Message pool header pointer sPool is a static variable of type Message, which means that all Messages share the same Message pool.

  • Obtain () then there must be another way to obtain messages from the Message pool, which is to fill in the pool with messages. Search the Message class for where sPool uses information and find the following method:

/** * Recycles a Message that may be in-use. * Used internally by the MessageQueue and Looper when disposing of queued Messages. */ void recycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Flags = FLAG_IN_USE; flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; Synchronized (sPoolSync) {// restrict the size of the message pool if (sPoolSize < MAX_POOL_SIZE) {//1. Next = sPool; SPool = this; sPool = this; sPoolSize++; }}}Copy the code
  • Just as you guessedrecycleUnchecked()Inserts the current message into the header of the message chain. Here is the following

  • At this point, we know that “messages from the pool eventually go back to the pool,”When exactly do messages get recycled into the message pool?Good question! This question will not be answered until the message distribution is analyzed. But now we can take a wild guess:The plate carrying the sushi will be recycled by the kitchen after the sushi is eaten. Is the message recycled after being processed?

conclusion

The “construct message” part of the Android messaging mechanism is over. To sum up: the life cycle of a message goes through “create, recycle, reuse”, all messages share a linked list structure message pool, which is used to store the recycled messages.

This is not the end of the story, but the next one will cover the distribution of messages