Handlerthread
1.run () Method
Handlerthread from the inheritance relationship, it inherits the thread class, which can be learned that this class is actually a thread class, since it is a thread class, then it must be rewritten in the thread of the Run () method, so you can browse the next run () method
From the three methods of the red arrow, see There are three methods, Looper.prepare (), Looper.mylooper (), Looper.loop (), and these three methods are actually three methods to invoke when the child thread creates the handler, In the Handlerthreadle class, the difference from other classes is that a looper is created that enables it to create handler objects in that thread
1.1 run () synchronized and Notifyall in the method
Typically, as long as the Synchronized keyword is present, it often means that there is a thread-safety problem here, and the Notifyall () method in thread is called to wake up other threads, and here it should be inferred that, since the Notifyall method is called, Then there is a good chance that the wait () method is used elsewhere, and the location of the call can be seen in the Getlooper method
2.getLooper () Method
There is a line of comments in this method, which presumably means that if the thread has been created, but Looper has not yet been created, the thread needs to enter the wait () state, waiting for the Looper object to be created, when the Looper object is in the run () Method is created by Looper.mylooper (), the Notifyall () method is called immediately before the thread in the wait () state is awakened
3. the Quit () method and the quitsafely () method
3.1 Use
The purpose of both methods is to terminate Looper, because each time a Handlerthread object is created, calling the run () method creates a Looper object, and Looper is a dead loop, which consumes a lot of resources, so the correct way to do this is, When the interface is destroyed, call the Quit () method or the Quitsafely () method to stop the Looper
3.2 Source Code
Two methods look very similar, the difference is that a call to the Looper object in the Quit () method, the other called the Quitsafely () method, follow the source
The mqueue in the figure is actually a MessageQueue object, and the two methods ultimately call the Quit method in MessageQueue, except that the arguments passed in are true and false, respectively.
View the Quit method in MessageQueue
The incoming Boolean value is ultimately judged here, if true, which is called the quitsafely () method, then the removeallfuturemessageslocked () method is executed, and if False, then the call is quit ( ) method, and finally the removeallmessageslocked () method is executed.
Continue to follow the removeallfuturemessagelocked () method, which will also call Method Removeallmessagelocked (),
One common denominator of these two methods is that when a method is called, Looper no longer receives a new message,
The difference is that without a future method, all types of messages in the message queue will be emptied, whether deferred or immediately executed, and with the future method, only the deferred message is cleared out, for non-deferred messages, it will be handed over to handler to execute.
The image above is the source of processing,
But why N.when > now can jump out of the loop, meaning that there is no immediate message?
This is due to the relationship of MessageQueue message queue processing, which is simply understood as the MessageQueue message queue is sorted from morning to night according to the processing time of the message
4. Introduction to how MessageQueue inserts messages
When handler sends a message out, the message is inserted into the message queue, but not without a brain inserting the message at the very end, first looking at some of the member properties in the message
When: is the execution time of this message, which is to determine whether the message is a delay message, and how long it will be delayed
Data: This is the information that is carried in this message, and you can see that the message is handled using bundles
Next: is a Message object, there is a line of comments, presumably the consciousness is sometimes need to use next to store some chain relations, which is similar to the structure of the list, linked list structure has head pointers, such as the concept of the head node, which assumes mmessage Always point to the first Message in a queue
When a new message is sent over, a split-case analysis,
first Case , satisfy the judgment condition in the first place, then let Mmessages point to this new inserted message, then what is the condition in the first place? Please see the source code below
Familiar with handler source should know, handler send a message, regardless of which method to call, ultimately by Sendmessageattime () This method to execute, and handler Sendmessageattime () Method calls this Enqueuemessage () method, in Enqueuemessage () This method, the first message object Mmessage assigned to a Message object p, and then the P is a few columns to judge,
P = = null: This judgment indicates whether the Mmessage object in the message queue is NULL, and if it is null, then the entire message queue is empty at this point, so the new message can be placed in the first position if this condition is met
When = = 0: When is handler send a message when the incoming message trigger time, if 0, indicating that the message is a non-deferred message, need to execute immediately, when the new message will be put to the first one,
When < p.when: that is, the trigger time of the new message sent by handler, less than the trigger time of the first message, then put it in the first position.
As long as the above three cases are met, then let Mmessage point to the newly inserted message,
Source
The second case
That is, the trigger time of the newly sent message msg, which is later than the mmessage time, then compares the when of MSG with the time of each of the Times behind the message queue until it meets the order from morning to night.
You can see that there is a dead loop in the source code, will always determine whether the message queue after the message, as well as the trigger time, when any one of the conditions, will stop the circular judgment, and then insert the new message msg into the queue
The source can see the declaration of a new Message object prev, this object always points to the MSG of the previous message
The following is the process diagram, the figure of 0x1010 and other assumptions as the address of the message, only for the understanding of reference, not the real address, so whenever, Prev always record is the previous address of P
When the new message msg finds the location, that is, Prev.when < Msg.when < P.when, the MSG is inserted after the Prev, before p this position
So far, the new message msg is inserted into the MessageQueue queue.
If there is any mistake, please correct me, thank you!
Android Source Learning-----Handlerthread