Before analyzing the android message mechanism, let's take a look at the Code:
Public class mainactivity extends activity implements view. onclicklistener {private textview statetext; private button BTN; @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); statetext = (textview) findviewbyid (R. id. TV); BTN = (button) findviewbyid (R. id. BTN); BTN. setonclicklistener (this) ;}@ overridepublic void onclick (view v) {New workthread (). start () ;}// work thread private class workthread extends thread {@ overridepublic void run (){//...... process time-consuming operations // status changes after processing is completed statetext. settext ("completed ");}}}
This Code seems to be normal, but when you run it, you will find that it reports a fatal exception:
ERROR/AndroidRuntime(421): FATAL EXCEPTION: Thread-8ERROR/AndroidRuntime(421): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
What is going on? The reason is that the view component in the Android system is not thread-safe. to update a view, the view must be updated in the main thread. The update operation cannot be performed in the Child thread.
In this case, we will notify the main thread in the Child thread and let the main thread perform the update operation. So how do we notify the main thread? We need to use the handler object.
Let's slightly modify the above Code:
Public class mainactivity extends activity implements view. onclicklistener {Private Static final int completed = 0; private textview statetext; private button BTN; private handler = new handler () {@ overridepublic void handlemessage (Message MSG) {If (MSG. what = completed) {statetext. settext ("completed") ;}};@ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); statetext = (textview) findviewbyid (R. id. TV); BTN = (button) findviewbyid (R. id. BTN); BTN. setonclicklistener (this) ;}@ overridepublic void onclick (view v) {New workthread (). start () ;}// work thread private class workthread extends thread {@ overridepublic void run (){//...... processing time-consuming operations // send message MSG = new message (); MSG to handler after processing is complete. what = completed; handler. sendmessage (MSG );}}}
In this way, we can solve the thread security problem by handing over the complex task processing work to the subthread for completion, and then the subthread notifies the main thread through the handler object, the message mechanism plays an important role in updating the view by the main thread.
Next, let's analyze the message mechanism in Android.
Friends familiar with Windows Programming know that Windows programs are message-driven and have a global message loop system. Google has referenced the message Loop Mechanism in windows and implemented the message Loop Mechanism in Android. Android uses logoff and handler to implement the message loop mechanism. The message loop of Android is for threads. Each thread can have its own message queue and message loop.
Logoff In the Android system is responsible for managing the message queues and message loops of threads. Obtain the logoff object of the current thread through logoff. mylogoff (), and obtain the logoff object of the main thread of the current process through loaning. getmainlogoff.
As mentioned above, the message queues and message loops of Android are for specific threads. A thread can have a message queue and a message loop. messages of a specific thread can only be distributed to this thread, cross-thread and cross-process communication is not allowed. However, the created worker thread does not have a message queue or a message loop by default. To enable a worker thread to have a message queue or a message loop, you must first call logoff in the thread. prepare () to create a message queue, and then call logoff. loop () enters the message loop. The following is the created worker thread:
Class workthread extends thread {public handler mhandler; Public void run () {loid. prepare (); mhandler = new handler () {public void handlemessage (Message MSG) {// process received message}; Looper. loop ();}}
In this way, the created worker thread has the message processing mechanism.
So, why do we not see the call of lorule. Prepare () and lorule. Loop () in the example of the front edge? The reason is that our activity is a UI thread. When running in the main thread, the android system creates a message queue and a message loop for the activity at startup.
Messagequeue and loopback are the most mentioned above. But we can see that handler exists in each message processing place. What does it do? Handler is used to add a message to the Message Queue managed by a specific logoff, and distribute and process the messages in the message queue. When constructing a handler, you can specify a logoff object. If this parameter is not specified, The logoff object of the current thread is used to create a logoff object. The following are two handler constructor methods:
/** * Default constructor associates this handler with the queue for the * current thread. * * If there isn't one, this handler won't be able to receive messages. */ public Handler() { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = null; }/** * Use the provided queue instead of the default one. */ public Handler(Looper looper) { mLooper = looper; mQueue = looper.mQueue; mCallback = null; }
The following figure shows the relationship between several important members of the message mechanism:
Multiple worker threads can be created in an activity. If these threads put their messages into the message queue of the activity main thread, the messages will be processed in the main thread. The main thread is generally responsible for updating view components. For view components that are not thread-safe, this method can effectively Update views.
So how does the subthread put messages into the message queue of the main thread? As long as the handler object is created with the Logoff of the main thread, when the sendmessage method of handler is called, the system will queue the message of the main thread, in addition, messages in the main thread message queue will be processed when the handlemessage method is called.
If a sub-thread accesses the handler object of the main thread, you may ask that multiple sub-threads access the handler object of the main thread, will data inconsistency occur during message sending and Message Processing? The answer is that the handler object will not be faulty, because the logoff object managed by the handler object is thread-safe. Both the addition of messages to the message queue and the reading of messages from the message queue are guaranteed synchronously, therefore, data inconsistency does not occur.
An in-depth understanding of the android message processing mechanism is very important for application development. It also gives us a deeper understanding of thread synchronization. I hope this article will be helpful to our friends.
Article reprinted Source: http://blog.csdn.net/liuhe688/article/details/6407225 #