This example describes the messaging mechanism in Android programming. Share to everyone for your reference, specific as follows:
Before we analyze the Android messaging mechanism, let's look at a piece of 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);
}
@Override public
void OnClick (View v) {
new Workthread (). Start ();
}
Worker thread
Private class Workthread extends thread {
@Override public
void Run () {
//...
change the State
Statetext.settext ("completed") after processing the more time-consuming operations//processing;
This code seems to look normal, but when you run it will find that it will report a fatal exception:
Error/androidruntime (421): FATAL exception:thread-8
Error/androidruntime (421): android.view.viewroot$calledfromwrongthreadexception:
Only the original thread this created a view hierarchy can touch it views.
What the hell is going on here? The reason is that the view component in the Android system is not thread-safe, and if you want to update the view, you must update it in the main thread, and you cannot perform the update operation in the child thread.
In this case, we are in the child thread to notify the main thread, let the main thread do the update operation. So how do we inform the main thread? We need to use the handler object.
Let's modify the above code a little bit:
public class Mainactivity extends activity implements View.onclicklistener {private static fi
nal int COMPLETED = 0;
Private TextView Statetext;
Private Button btn; Private Handler Handler = new Handler () {@Override public void Handlemessage (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);
@Override public void OnClick (View v) {new Workthread (). Start (); }//worker thread private class Workthread extends thread {@Override public void run () {//...
Send a message to handler after handling the more time-consuming operations//processing: msg = new messages ();
Msg.what = COMPLETED;
Handler.sendmessage (msg); }
}
}
In this way, we can solve the problem of thread security, the complex task processing work to the child thread to complete, and then the child thread through the handler object to inform the main thread, the main thread to update the view, the process of the message mechanism plays an important role.
Let's take a look at the messaging mechanism in Android.
Friends who are familiar with Windows programming know that Windows programs are message-driven and have a global messaging loop. Google has consulted the Windows message-cycling mechanism and implemented the message-looping mechanism in the Android system. Android uses Looper, handler to implement the message loop mechanism. The android message loop is thread-specific, and each thread can have its own message queue and message loop.
The Looper in the Android system is responsible for managing the thread's message queues and message loops. The Looper object of the current thread is obtained by Looper.mylooper (), and the Looper object of the main thread of the current process is obtained by Looper.getmainlooper ().
As mentioned earlier, both message queues and message loops for Android are specific threads, and a thread can have a message queue and a message loop where messages from a particular thread are distributed only to this thread and cannot be communicated across threads and across processes. However, the worker threads created by default do not have Message Queuing and message loops, and if you want a worker thread to have Message Queuing and message loops, you need to call Looper.prepare () first in the thread to create the message queue, and then call Looper.loop () into the message loop. Here is the worker thread we created:
Class Workthread extends Thread {public
Handler Mhandler;
public void Run () {
looper.prepare ();
Mhandler = new Handler () {public
void Handlemessage (msg) {
//processing received message
}
};
Looper.loop ();
}
This way, the worker threads we create have a message handling mechanism.
So, why do we not see Looper.prepare () and Looper.loop () calls in the front example? The reason is that our activity is a UI thread that runs in the main thread, and the Android system creates a message queue and a message loop for the activity when it starts.
The most mentioned above are Message Queuing (MessageQueue) and Message loops (Looper), but we see that every message processing place has a handler presence, what does it do? The role of handler is to add messages to a message queue managed by a specific looper and to distribute and process messages in that message queue. When constructing a handler, you can specify a Looper object that, if not specified, is created with the Looper object of the current thread. The following are two construction methods for handler:
/** * Default Constructor Associates This handler with the queue for the * current thread.
* * If there isn ' t one, this handler won ' t is 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:"
+ Klass.getcanonicalname ());
} Mlooper = Looper.mylooper (); if (Mlooper = = null) {throw new RuntimeException ("Can" t create handler inside thread that is has not called L
Ooper.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 is a diagram of several important members of the message mechanism:
Multiple worker threads can be created in an activity, and if the threads put their messages in the message queue of the activities main thread, the message is processed in the main thread. Because the main thread is typically responsible for updating the view components, this approach is a good way to implement the view update for a view component that is not thread safe.
So how does a child thread put a message into the main thread's message queue? As long as the handler object is created with the looper of the main thread, when the SendMessage method of the handler is invoked, the system takes message queues of the message main thread and will process the message in the main thread message queue when the Handlemessage method is invoked.
For child threads accessing the handler object of the main thread, you may ask that multiple child threads access the main thread's handler object, and will there be inconsistencies in the data when sending and processing messages? The answer is that the handler object does not have a problem because the Looper object managed by the handler object is thread-safe, and no data inconsistency occurs, whether it is to add a message to a message queue or read a message from a message queue is synchronously protected.
An in-depth understanding of the Android messaging mechanism is important for application development, and it also allows us to have a deeper understanding of thread synchronization, and hopefully this article will help friends.
I hope this article will help you with the Android program.