Message Processing Mechanism in Android Development (II) -- message loop
/*
* Message Processing Mechanism developed by Android (2)-message loop
* Beijing Android Club group: 167839253
* Created on: 2011-9-1
* Author: blueeagle
* Email: liujiaxiang@gmail.com
*/
First, we will introduce how to use background threads and UI threads in Android applications.
The most flexible way to create an Android-friendly background thread is to create an instance of the handler subclass. Each activity requires only one handler object and does not need to be manually registered.
The background thread can communicate with handler. handler will execute all his work on the UI thread of the activity. This is very important. The UI changes can only happen on the UI thread of the activity.
There are two ways to communicate with handler: Message and runnable object.
About message:
To send a message to handler, call obtainmessage () to obtain the message object from the pool. The obtainmessage () object has many features. It allows you to create an empty message object or an object that is filled with message identifiers and parameters. The more complicated the handler processing process is, the more data needs to be placed in the message to help handler distinguish different events.
Then, the message can be sent to Handler through the message queue. In this case, sendmessage... () A method in the series of methods.
Sendmessage (); immediately put the message in the queue.
Sendmessageatfrontofqueue (); immediately put the message in the queue and put it at the beginning of the message queue, so that the message has a higher priority than all other messages.
Sendmessageattime (); put the message in the queue at the specified time. This time is represented by MS and is based on the normal operating time of the system. (Systemclock. uptimemillis ())
Sendmessagedelayed (); put the message in the queue after a delay, and the delay is represented by Ms.
To process these messages, Handler needs to implement handlemessage () and calls handlemessage () using each message that appears in the message queue (). Handler can update the UI as needed. However, it should still do this quickly, because other UI work will be paused before it completes.
About runnable:
If you do not want to use the message object, you can also pass the runnable object to handler. handler will run these runnable objects on the activityui thread. Handler provides a set of post... () Method to pass in the runnable object for final processing.
The understanding of the message loop mechanism of android can be modeled in the Windows message loop mechanism.
Each handler is associated with the message queue of a thread and thread. At this time, you can pass the messages and runnable objects to the message queue. This object can be extracted from message queue and executed later. Handler and message queue the interaction between the two objects involves logoff.
Shows the relationship between handler, logoff, and message queue:
Handler has many Constructors
Handler calls the logoff. mylogoff () method in the construction method without parameters. It obtains a logoff from the current thread and initializes messagequeue together, and obtains the logoff messagequeue. It can be seen that handler is the manager and dispatcher of logoff and messagequeue.
The most important method is the sendmessageattime method. When you send a message to handler, the Code shows that he does not process the message, but gives it to messagequeue, which is used by queue. enqueuemessage.
The logoff code contains a prepare () method. threadlocal is used to implement a thread with only one logoff.
Handler message sending
Handler is the core of message creation, acquisition, and processing. The sendmessage () method of handler is actually calling queue. enqueuemessage (MSG, uptimemillis); put the message into message queue. After detecting a message through logoff. Loop () and broadcasting the message, the handler is responsible for receiving the message and calling handlemessage to process the next thing. The message is generally created using the following code and the handler is passed in.
Public final message obtainmessage ()
{
Return message. Obtain (this );
}
This method is shown in:
Message is a linked list structure. In this method, the messagepool (Message recycle bin) is used to find the message first. If a recycled message exists, the message is retrieved for reuse. If a message object is not recycled, the system will actually generate a new message object. Of course, messagepool is not infinitely large. It can only store up to ten recycled messages, and delete them if it is not recycled.
So far, we can see that a message is created and sent by handler, messagequeue is queued, logoff is extracted, and then return to handler for processing again. This circle also helps us change the synchronous operation into an asynchronous operation.
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. Before creating a handler, prepare a looper (Looper. Prepare) for the thread, and then let the looper run (Looper. Loop) to extract the message so that the handler can work properly.
Therefore, Handler always processes messages in the thread of creating handler.
The following is an example based on the above theoretical knowledge:
Example 1:
Call the POST method of handler in the UI thread. The Code is as follows:
/** Message Processing Mechanism developed by Android (2) -- message loop * messagecircle. java * created on: 2011-9-2 * Author: blueeagle * Email: liujiaxiang@gmail.com */package blueeagle.com; import android. app. activity; import android. OS. bundle; import android. OS. handler; public class messagecircle extends activity {/** called when the activity is first created. */private handler myhandler = new handler (); Private runnable myrunnable = new runnable () {@ overridepublic void run () {try {thread. sleep (1000);} catch (interruptedexception e) {e. printstacktrace ();} system. out. println ("Current runnable thread ID:" + thread. currentthread (). GETID () ;}}; @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); system. out. println ("Current Activity thread ID:" + thread. currentthread (). GETID (); myhandler. post (myrunnable );}}
The program running result is as follows:
In this program, we have a new handler object myhandler without parameters. This myhandler is automatically associated with the current running program, that is, this myhandler uses the same message queue as the currently running thread and can process messages in the queue.
In the program code, this myhandler posts a myrunnable object to the message queue. In the run method of myrunnable, print the ID of the current thread. The result shows that the new myhandler sends the message or runnable object to the current thread. Here we do not call the START () function of the thread, so we will not create a new thread. Instead, the run () method is called directly within the original thread. Therefore, the output IDs are the same.
So how to create a new thread? In the message processing mechanism of Android Development (I), we already know how to create a new thread. Here we will continue to provide an example for comparison.
Example 2:
First, you must create a thread, which can be a self-created thread or handlerthread. This thread must inherit from the Thread class or implement the runnable interface. Next, we need a handler. This handler can be a handler or inherit from the handler and requires a constructor with The logoff parameter. Then the message can be distributed and executed.
The sample code is as follows:
/** Message Processing Mechanism developed by Android (2) -- message loop * messagecircle. java * created on: 2011-9-2 * Author: blueeagle * Email: liujiaxiang@gmail.com */package blueeagle.com; import android. app. activity; import android. OS. bundle; import android. OS. handler; import android. OS. handlerthread; import android. OS. logoff; import android. OS. message; import android. widget. textview; public class messagecircle extends activity {public class Myownthread extends thread {int sleepspan = 2000; // sleep time boolean flag; // indicates the thread execution flag bit // -------------------------------- // constructor, initialize the main member variable public myownthread () {This. flag = true;} // -------------------------------- // method, thread execution method @ override public void run () {textview mytextview = (textview) findviewbyid (R. id. mytextview); logoff. prepare (); int I = 1; while (FLAG) {try {thread. sleep (sleepspan); // sleep 1 System. out. println ("Current myownthread thread ID:" + thread. currentthread (). GETID (); mytextview. settext (I); I ++;} catch (exception e) {e. printstacktrace (); // capture exceptions and print} logoff. loop () ;}} public class myhandler extends handler {public myhandler () {}public myhandler (Looper loler) {super (lode) ;}@ override public void handlemessage (Message MSG) {system. out. println ("Current myhandle thread ID: "+ Thread. currentthread (). GETID (); textview mytextview = (textview) findviewbyid (R. id. mytextview); int I = 1; while (true) {try {thread. sleep (1000); // sleep for a period of time system. out. println ("Current myhandle thread ID:" + thread. currentthread (). GETID (); mytextview. settext ("I"); I ++;} catch (exception e) {e. printstacktrace (); // capture an exception and print it }}}/** called when the activity is first created. */private myhandler myhandl ER = NULL; @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); system. out. println ("Current Activity thread ID:" + thread. currentthread (). GETID (); // myhandler. post (myrunnable); handlerthread mythread = new handlerthread ("mythread"); // generate a handlerthread object and use logoff to process message queues. Mythread. Start (); // start this thread myhandler = new myhandler (mythread. getloler (); // bind a thread to the myhandler object. Message MSG = myhandler. obtainmessage (); // obtain the message MSG from the object myhandler. sendtotarget (); // send the MSG object to the handler of the target. // create your own thread myownthread = new myownthread (); myownthread. start ();}}
The method for updating the UI by threads has been described in (1. The following uses an example to display the message loop process for music playing. The example of updating the lyrics in the UI thread describes the message processing mechanism. The example is simple and does not implement synchronization of lyrics. Only to better understand the thread running status.
According to the above theory: the code is as follows:
/** Message Processing Mechanism developed by Android (2)-message loop * musicplayer. java * created on: 2011-9-3 * Author: blueeagle * Email: liujiaxiang@gmail.com */package blueeagle.com; import android. app. activity; import android. media. mediaplayer; import android. OS. bundle; import android. OS. handler; import android. OS. logoff; import android. OS. message; import android. view. view; import android. view. view. onclicklistener; import android. widget. button; import android. widget. textview; public class musicplayer extends activity {/** called when the activity is first created. */button mybutton; textview mytextview; private uiupdatethread myupdatethread = new uiupdatethread (); // defines a self-defined UI update Thread class myhandler mhandler = new myhandler (); // define your own handler class @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); mybutton = (button) findviewbyid (R. id. mybutton); mytextview = (textview) findviewbyid (R. id. mytextview); mybutton. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {// todo auto-generated method stub system. out. println ("main thread running ID:" + thread. currentthread (). GETID (); new thread (myupdatethread ). start (); // start a self-defined thread});} class myhandler extends handler {// when inheriting the handler class, you must override the handlemessage method public myhandler () {} public myhandler (Looper L) {super (l) ;}@ overridepublic void handlemessage (Message MSG) {// execute the notification received, in this case, the execution order is based on the queue, that is, the mytextview is obtained first. settext (MSG. tostring (); system. out. println ("Current handler thread ID:" + thread. currentthread (). GETID () ;}} // This thread will run class uiupdatethread implements runnable {int I = 1; Public void run () in a separate thread () {While (I <11) {message MSG = mhandler. obtainmessage (); mhandler. sendmessage (MSG); system. out. println ("New thread running ID:" + thread. currentthread (). GETID (); I ++; try {thread. sleep (4000);} catch (interruptedexception e) {// todo auto-generated Catch Block E. printstacktrace ();}}}}}
The source code for simple music playback is as follows:
/** Message Processing Mechanism developed by Android (2)-message loop * musicplayer. java * created on: 2011-9-3 * Author: blueeagle * Email: liujiaxiang@gmail.com */package blueeagle.com; import android. app. activity; import android. media. mediaplayer; import android. OS. bundle; import android. OS. handler; import android. OS. logoff; import android. OS. message; import android. view. view; import android. view. view. onclicklistener; import android. widget. button; import android. widget. textview; public class musicplayer extends activity {/** called when the activity is first created. */private mediaplayer MP; button mybutton; textview mytextview; private uiupdatethread myupdatethread = new uiupdatethread (); // defines a self-defined UI update Thread class myhandler mhandler = new myhandler (); // define your own handler class @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); mybutton = (button) findviewbyid (R. id. mybutton); mytextview = (textview) findviewbyid (R. id. mytextview); mybutton. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {// todo auto-generated method stubmp = mediaplayer. create (musicplayer. this, R. raw. yinweiaiqing); MP. start (); system. out. println ("main thread running ID:" + thread. currentthread (). GETID (); new thread (myupdatethread ). start () ;}});} class myhandler extends handler {// when inheriting the handler class, you must override the handlemessage method public myhandler () {} public myhandler (Looper L) {super (l) ;}@ overridepublic void handlemessage (Message MSG) {// execute the notification received. The execution order is based on the queue, that is, output mytextview first. settext (MSG. OBJ. tostring (); system. out. println ("Current handler thread ID:" + thread. currentthread (). GETID () ;}}// this thread will run class uiupdatethread implements runnable {int I = 0; string mystring [] = {"this is a real-time playing thread operation ...... "," [00: 08. 79. 46] E. Give you a previous CD. 68] Listen to our love at that time. 12] Sometimes I suddenly forget. 48] I still love you. 98] F cannot sing such a song any more. 48] You will face your face in red. 83] Although I often forget. 33] I still love you. 49] f because love is not easy to sad. 49] f because love is not easy to sad. 09] E. So everything is happy. 24] f Simple growth of Love. 24] e can still be crazy for you at any time. 21] f how can there be vicissitudes of life in love. 30] E, so we are still young. 90] f because love is in that place. 32] e still has people wandering there. 91] E & F. 57] f no more songs like that. 70] You will face your face in red. 14] Although I often forget. 26] E & F I still love you. 60] f because love is not easy to sad. 22] E. So everything is happy. 98] f Simple growth of Love. 36] e can still be crazy for you at any time. 38] f how can there be vicissitudes of life in love. 94] E, so we are still young. 04] f because love is in that place. 63] e still has people wandering there. 04] E & F. 98] E. Give you a previous CD. 58] Listen to our love at that time. 48] f sometimes suddenly forgets. 94] E & F I still love you "}; Public void run () {While (MP. isplaying () {message MSG = mhandler. obtainmessage (1, 1, 1, mystring [I]); mhandler. sendmessage (MSG); system. out. println ("New thread running ID:" + thread. currentthread (). GETID (); try {thread. sleep (4000); I ++; if (I = mystring. length) {I = mystring. length-1 ;}} catch (interruptedexception e) {// todo auto-generated Catch Block E. printstacktrace ();}}}}}
To sum up, I have a basic understanding of some concepts about threads and message loops in Android. I also need to have a deep understanding of how logoff is used in the program.