A brief analysis of the message mechanism in Android-Solution: Only the original thread, created a view hierarchy can touch its views.

Source: Internet
Author: User

Before analyzing the Android messaging mechanism, let's look at a piece of code:

[HTML]View Plaincopyprint?
  1. public class Mainactivity extends Activity implements View.onclicklistener {
  2. Private TextView Statetext;
  3. Private Button btn;
  4. @Override
  5. public void OnCreate (Bundle savedinstancestate) {
  6. Super.oncreate (savedinstancestate);
  7. Setcontentview (R.layout.main);
  8. Statetext = (TextView) Findviewbyid (r.id.tv);
  9. btn = (Button) Findviewbyid (R.ID.BTN);
  10. Btn.setonclicklistener (this);
  11. }
  12. @Override
  13. public void OnClick (View v) {
  14. New Workthread (). Start ();
  15. }
  16. Worker threads
  17. Private class Workthread extends Thread {
  18. @Override
  19. public void Run () {
  20. //...... Handle more time-consuming operations
  21. Change status after processing is complete
  22. Statetext.settext ("completed");
  23. }
  24. }
  25. }

This code seems to look normal, but when you run it you will find that it will report a fatal exception:

[HTML]View Plaincopyprint?
    1. Error/androidruntime (421): FATAL exception:thread-8
    2. Error/androidruntime (421): android.view.viewroot$calledfromwrongthreadexception:
    3. Only the original thread, created a view hierarchy can touch its views.


What the hell is going on here? The reason is that the view components in the Android system are not thread-safe, and if you want to update the view, you must update it in the main thread, and you cannot perform the updated operation on the child thread.

In this case, we will notify the main thread in the child threads, let the main thread do the update operation. So how do we notify the main thread? We need to use the handler object.

Let's modify the above code a little bit:

[HTML]View Plaincopyprint?
  1. public class Mainactivity extends Activity implements View.onclicklistener {
  2. private static final int completed = 0;
  3. Private TextView Statetext;
  4. Private Button btn;
  5. Private Handler Handler = new Handler () {
  6. @Override
  7. public void Handlemessage (Message msg) {
  8. if (msg.what = = completed) {
  9. Statetext.settext ("completed");
  10. }
  11. }
  12. };
  13. @Override
  14. public void OnCreate (Bundle savedinstancestate) {
  15. Super.oncreate (savedinstancestate);
  16. Setcontentview (R.layout.main);
  17. Statetext = (TextView) Findviewbyid (r.id.tv);
  18. btn = (Button) Findviewbyid (R.ID.BTN);
  19. Btn.setonclicklistener (this);
  20. }
  21. @Override
  22. public void OnClick (View v) {
  23. New Workthread (). Start ();
  24. }
  25. Worker threads
  26. Private class Workthread extends Thread {
  27. @Override
  28. public void Run () {
  29. //...... Handle more time-consuming operations
  30. Send message to Handler when processing is complete
  31. Message msg = new Message ();
  32. msg.what = completed;
  33. Handler.sendmessage (msg);
  34. }
  35. }
  36. }


In this way, we can solve the problem of thread safety, the complex task processing 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 look at the message mechanism in Android.

A friend familiar with Windows programming knows that Windows programs are message-driven and have a global messaging system. Google has referenced the Windows message loop mechanism, and also implemented a message loop mechanism in the Android system. Android uses Looper, handler to implement the message loop mechanism. The message loop for Android 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 thread Message Queuing and message loops. The Looper object of the current thread is obtained through Looper.mylooper (), and the Looper object of the current process's main thread is obtained through Looper.getmainlooper ().

As mentioned earlier, both the message queue and message loop for Android are specific threads, one thread can have a message queue and a message loop, and a particular thread's message can only be distributed 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 the worker thread to have Message Queuing and message loops, you will need to call Looper.prepare () to create the message queue in the thread and then call Looper.loop () to enter the message loop. Here are the worker threads we created:

[HTML]View Plaincopyprint?
  1. Class Workthread extends Thread {
  2. Public Handler Mhandler;
  3. public void Run () {
  4. Looper.prepare ();
  5. Mhandler = new Handler () {
  6. public void Handlemessage (Message msg) {
  7. Process the received message
  8. }
  9. };
  10. Looper.loop ();
  11. }
  12. }


In 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 preceding 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 message loop for the activity when it starts.

The most mentioned is Message Queuing (MessageQueue) and message loop (Looper), but we see that every message processing place has a handler existence, what does it do? The role of handler is to add messages to a message queue that is managed by a particular looper and to distribute and process messages in that message queue. When constructing handler, you can specify a Looper object that is created with the Looper object of the current thread if not specified. Here are the two construction methods for handler:

[HTML]View Plaincopyprint?
  1. /**
  2. * Default Constructor Associates This handler with the queue for the
  3. * Current thread.
  4. *
  5. * If there isn ' t one, this handler won ' is able to receive messages.
  6. */
  7. Public Handler () {
  8. if (Find_potential_leaks) {
  9. Final Class<?  extends Handler> klass = getclass ();
  10. if (Klass.isanonymousclass () | | klass.ismemberclass () | | klass.islocalclass ()) &&
  11. (Klass.getmodifiers () & modifier.static) = = 0) {
  12. LOG.W (TAG, "the following Handler class should be static or leaks might occur:" +
  13. Klass.getcanonicalname ());
  14. }
  15. }
  16. mlooper = looper.mylooper ();
  17. if (mlooper = = null) {
  18. throw New RuntimeException (
  19. "Can ' t create handler inside thread that have not called looper.prepare ()");
  20. }
  21. mqueue = mlooper.mqueue;
  22. mcallback = null;
  23. }
  24. /**
  25. * Use the provided queue instead of the default one.
  26. */
  27. Public Handler (Looper Looper) {
  28. mlooper = looper;
  29. mqueue = looper.mqueue;
  30. mcallback = null;
  31. }


Here is a diagram of several important members of the messaging mechanism:

In one activity, multiple worker threads can be created, and if those threads put their messages in the message queue of the activity's main thread, the message is processed in the main thread. Because the main thread is generally responsible for updating the view component, this 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 the message into the message queue of the main thread? As long as the handler object is created with the looper of the main thread, when the SendMessage method of handler is called, the system puts the message queue of the main thread of the message, and the message in the main thread message queue is processed when the Handlemessage method is called.

For a child thread to access the handler object of the main thread, you might ask that many sub-threads have access to the handler object of the main thread, and that data inconsistencies will occur during the sending and processing of messages. The answer is that there is no problem with the handler object, because the Looper object managed by the handler object is thread-safe, regardless of whether the message is added to the message queue or read from the message queue is synchronously protected, so there is no data inconsistency.

In-depth understanding of the Android message processing mechanism is very important for application development, but also allows us to have a deeper understanding of thread synchronization, I hope this article can help friends.


Articles reproduced at source: http://blog.csdn.net/liuhe688/article/details/6407225#

A brief analysis of the message mechanism in Android-Solution: Only the original thread, created a view hierarchy can touch its views.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.