Ask for help how to transfer the Jane book article to the nuggets ah, Jane book is too bad to use!! But wrote some articles in the above, want to directly migrate over what good p plus no, if you know, trouble teach me!! Thank you ~

Handler is usually asked these questions

  • 1. How many handlers does a thread have?
  • 2. How many loopers are there in a thread? How to guarantee?
  • 3. Why does Handler leak memory?
  • 4. Can a child thread have a new Handler?
  • 5. What is the Looper maintained in the child thread when there is no message in the message queue? What’s the use? What about the main thread?
  • 6. Since there can be multiple handlers to add data to MessageQueue (each Handler may be on a different thread when sending messages), how is it internally thread-safe? What about getting messages?
  • 7. How do we create Message when we use it

The overall framework of the Handler

The Handler processes

Handler is only responsible for putting messages into MessageQueue. MessageQueue is the conveyor belt, and many message Looper is the wheel of the conveyor belt. He drives the MessageQueue to run all the time. Thread is the power. Without threads, the entire transmission will not start, and Looper also provides a switch for threads to transmit only when turned on

MessageQueue and Message

Add a message

Whenever you send a Message using handler, you end up going to handler#enqueueMessag and calling MessageQueue#enqueueMessage, and you can see that the method needs to pass in a Message

handler#enqueueMessage

MessageQueue#enqueueMessage

MessageQueue also stores a mMessage variable. What does it doMessageWhat is the

MessageThat’s the body of the Message that we’re sending, and you can see in this class, inside a Message variable, there’s another Message callednext“To store the next Message, what’s the use of that

Once again return toMessageQueue#enqueueMessageWhat do these variables really do

Msg1. next = p = null, mMessage = MSg1

P = mMessage = msg1; p = mMessage = msg1 When (msG2.when) > p.hen (msg1.when) then the if statement is not true and the else statement for loop is entered

Prev = p = mMessage = msg1, p = p.ext (p = msg1, msg1.next = null), p = null

Next = p = null prev. Next (msg1.next) = msg2

So the structure looks like this, and by doing this assignment, you have a linked list structure so a MessageQueue is like a warehouse where you have a chain of messages

Take a message

The way to get the message isMessageQueue#next(Handler () method, we know that sending the message is called by handler

Well, it’s easy to know from the original picture, yesLoop#loop()It calls that method and it gets called when that method gets MSGmsg.target.dispatchMessage(msg)To send a message, msg.target is a handler

So they developed this model, this producer-consumer model

Looper.loop() is used to call the main thread to retrieve the message and distribute it. However, when we call the main thread, we use Handler directly. The main thread calls looper.loop () for us

Once you know the process, go back to the original question

1. How many handlers does a thread have?

Can’t the main thread use more than one Handler

2. How many loopers are there in a thread? How to guarantee?

The answer is simple, one Looper per thread, but how is that guaranteed?

So let’s look at how Looper is created, who created it and you can see that Looper’s constructor is only inprepareIt’s used here, and the system tells us,

But Looper is stored in the sThreadLocal variable, so let’s look at what sThreadLocal is and look at the ThreadLocal class which is a static variable in Looper

Let’s go to the sthreadLocal.set (Looper) method

  • Prepare () –> set() –> the current thread

If Thread1 calls prepare, the current thread, Thread1, cannot be used by any other thread.

  • 2. ThenThreadLocalMap is obtained by getMap(the current thread)That is, Thead is related to ThreadLocalMap. You can also see that Thread has a ThreadLocalMap variable in it

  • 3. The final will beThis (current ThreadLocal)The Looper passed in is saved in ThreadLocalMap
  • 4.ThreadLocalMap is a store of

    key-value pairs
    ,value>

So look at the relationship between Thread, ThreadLocalMap, ThreadLocal, and Looper

This ensures that a Thread corresponds to a ThreadLocalMap, which in turn stores the ThreadLocal of that Thread. <key,vaule> <key,vaule> <key,vaule> <key,vaule> <key,vaule> <key,vaule

Go back toprepareFunction, and you can see before new Looper, there’s another oneget()operation

Prepare can only be called once on a Thread, so Looper can only be generated once. Prepare can only be called once on a Thread, so Looper can only be generated once. That’s the only one

3. Why does Handler leak memory?

We know that handlers cannot exist as internal classes, or they might cause a memory leak. Why not other inner classes?

From Java syntax we know: An anonymous inner class holds an object from an external class such as this one. A handler holds a HandlerActivity, or it can’t call its methods. Handleractivity. this means that ** Handler holds everything in the Activity = a lot of memory **

First we know that a message is sent by a handler, and then the MessageQueue holds the message

When we look at Handler #enqueueMessage, I think the red box is the main cause of the memory leak. Traget = this means message holds the Handler object

MessageQueue — Hold –> Message — hold –> Handler — hold –> this.Activity — hold –> everything in the Activity = lots of memory

When the Handler sends a message with a delay of 10 seconds. But on 5s, the Activity is destroyed. At this point, the message is not processed, even if it has been thrown from MessageQueue, but the Activity destroys and no one receives it, that is, if the message exists, the link above is still alive. So there’s a lot of memory that’s not being handled, and the virtual machine will think that you’re holding it, and it won’t reclaim it, and that’s a memory leak.

So Handler memory leaks are due to anonymous inner classes that are not comprehensive enough

4. Can a child thread have a new Handler?

The answer is yes. The main thread and the child thread are both threads, why not the child thread, and I’ve seen so much code that I don’t see where the main thread has to execute the method.

To create a Handler for a child thread, you need to create your own Looper in the thread

We then pass the child thread’s Looper to the Handler, and the Handler is created by the child thread

Student: But is there a problem with writing this, of course there is we know that the child thread is asynchronous, and when the child thread generates and gets the Looper, how do you know when it’s ready to be created, how do you know that when the Handler is created, the Looper has a value? Now it’s a thread synchronization problem. It’s simple. Thread synchronization locks. In fact, the system has already written a HandlerThread that creates a Handler in a child thread

So if we call getLooper before Looper is created, we execute wait(), release the lock, and wait until run gets the lock, NotiftAll () after getting the Looper is used to wake it up so that it is guaranteed to have a Looper when the Handler is created

5. What is the Looper maintained in the child thread when there is no message in the message queue? What’s the use? What about the main thread?

We know that Looper will fetch messages from MessageQueue for us. What will Looper do when there is no message from MessageQueue

First seeing the next() method that gets the message, he calls the native layer method nativePollOnce, which makes the thread wait when it doesn’t get the message

So in the looper.loop () method, the system also tells us that it will block here, whereas looper.loop () is running in the child thread’s run. If there is no message, it will block forever, the run method will never end, and the thread will never release, causing a memory leak

So Looper gave us a method called quitSafely, and he would call MessageQueue

So he’s going to make McOntract = true; “, then clears message, and then nativeWake, which is paired with nativePollOnce, wakes it up to continue execution

So after quitSafely, the next() method continues, because MSG = null and mquit = true, causing next() to return null directly

Looper.loop() (MSG: null); return (MSG: null); This will also free up the thread

6. Since there can be multiple handlers to add data to MessageQueue (each Handler may be on a different thread when sending messages), how is it internally thread-safe? What about getting messages?

We know that when Looper is created, a MessageQueue will be created and it is uniquely corresponding, which means that a Thread, Looper, and MessageQueue are uniquely corresponding relations

This of synchronized (this) is MessageQueue when the message is added, and according to the corresponding relationship, the lock here is actually equivalent to locking the current thread. If multiple handlers add messages to a thread at the same time, they will also be locked to ensure that the message is added in order, the same as the message

7. How do we create Message when we use it

I don’t know if any of you use New Message() to create messages. That’s fine, but if you have crazy new messages, every time you have a new Message, you’re taking up a chunk of memory, you’re taking up a lot of memory and memory fragmentation

The system also provides a way to create a new Message, but it’s still new Message(), so what’s the difference? The difference is sPool, which is also a Message variable

Back to Looper, he calls the Message method when a Message is not processed

The method is to empty all the parameters of the current Message into an empty Message object and drop it into sPool. When you need the Message variable later, he can repeat it inside