A few days ago, I discussed the message mechanism in Android with my colleagues and explored the message sending and receiving processes and the relationship with threads. Although we often use these basic things, our understanding of their internal Principles makes it easier and reasonable for us to structure the system and avoid some low-level errors.
This part is described in four sections:
1. responsibilities and relationships
2. Message Loop
3. threads and updates
4. Summary
Bytes --------------------------------------------------------------------------------------------------
1) Next, let's start with this part. First, let's take a look at our respective responsibilities and relationships.
Responsibilities
Message: contains the Message ID, the Message processing object, and the processed data. MessageQueue queues in a unified manner and is eventually processed by Handler.
Handler: the Handler responsible for sending and processing messages. When using Handler, you must implement the handleMessage (Message msg) method to process specific messages, such as updating the UI.
MessageQueue: a message queue used to store messages sent by Handler and run the messages according to FIFO rules. Of course, storing messages is not actually a matter of saving. Instead, messages are connected in a linked list, waiting for the logoff to be extracted.
Logoff: the Message pump constantly extracts messages from MessageQueue for execution. Therefore, a MessageQueue requires a logoff.
Thread: a Thread that schedules the entire message loop, that is, the execution location of the message loop.
Link
Handler, logoff, and MessageQueue are simple triangles. Logoff corresponds to MessageQueue one by one. When a logoff is created, a MessageQueue is created. The relationship between Handler and them is just a simple clustering relationship, that is, the Handler will reference the specific logoff and MessageQueue in the current thread.
In this way, multiple Handler can share the same loose and MessageQueue. Of course, these Handler will also run in the same thread.
2) Next, let's take a brief look at the message loop process:
Generate
Message msg = mHandler. obtainMessage ();
Msg. what = what;
Msg. sendToTarget ();
Send
MessageQueue queue = mQueue;
If (queue! = Null ){
Msg.tar get = this;
Sent = queue. enqueueMessage (msg, uptimeMillis );
}
In Handler. in the sendMessageAtTime (Message msg, long uptimeMillis) method of java, we can see that it finds the MessageQueue referenced by it, then set the target of the Message to itself (in order to find the correct Handler in the Message processing stage), and then include the Message into the Message queue.
Extraction
Lodomainme = mylodomain ();
MessageQueue queue = me. mQueue;
While (true ){
Message msg = queue. next (); // might block
If (msg! = Null ){
If (msg.tar get = null ){
// No target is a magic identifier for the quit message.
Return;
}
Msg.tar get. dispatchMessage (msg );
Msg. recycle ();
}
}
In logoff. in the loop () function of java, we can see that there is an endless loop here, constantly getting the next (next method) Message from MessageQueue, and then using the target information carried in the Message, by the correct Handler (dispatchMessage method ).
Processing
If (msg. callback! = Null ){
HandleCallback (msg );
} Else {
If (mCallback! = Null ){
If (mCallback. handleMessage (msg )){
Return;
}
}
HandleMessage (msg );
}
In Handler. in the dispatchMessage (Message msg) method of java, one of the branches is to call the handleMessage method to process this Message, this is exactly why handleMessage (Message msg) needs to be implemented when Handler is used.
As for another branch in the dispatchMessage method, I will explain it in the following content.
So far, we can see that a Message is sent by Handler, MessageQueue is in the queue, logoff is extracted, and then return to Handler's arms again. This circle also helps us change the synchronous operation into an asynchronous operation.
3) for the rest, we will discuss the thread in which Handler is located and how to update the UI.
In the main thread (UI thread), if the logoff object is not input when Handler is created, the logoff object of the main thread (UI thread) will be used directly (the system has already created it for us ); in other threads, if a Handler is not input when it is created, the Handler cannot receive and process messages. In this case, the general practice is:
Class LooperThread extends Thread {
Public Handler mHandler;
Public void run (){
Logoff. prepare ();
MHandler = new Handler (){
Public void handleMessage (Message msg ){
// Process incoming messages here
&