A brief analysis of the message mechanism in Android

Source: Internet
Author: User
<span id="Label3"></p><p><p>Before analyzing the Android messaging mechanism, Let's look at a piece of code:</p></p><p><p></p></p><strong><strong>[java]</strong></strong>View Plaincopy <ol class="dp-j" start="1"> <li class="alt"><li class="alt"><span class="keyword">Public <span class="keyword">class Mainactivity <span class="keyword">extends Activity <span class="keyword">implements View.onclicklistener {</span> </span> </span></span></li></li> <li><li></li></li> <li class="alt"><li class="alt"><span class="keyword">Private TextView statetext; </span></li></li> <li><li><span class="keyword">Private Button btn; </span></li></li> <li class="alt"><li class="alt"></li></li> <li><li><span class="annotation">@Override</span></li></li> <li class="alt"><li class="alt"><span class="keyword">public <span class="keyword">void OnCreate (Bundle Savedinstancestate) {</span> </span></li></li> <li><li><span class="keyword">super.oncreate (savedinstancestate); </span></li></li> <li class="alt"><li class="alt">Setcontentview (r.layout.main);</li></li> <li><li>Statetext = (TextView) Findviewbyid (r.id.tv);</li></li> <li class="alt"><li class="alt">BTN = (Button) Findviewbyid (r.id.btn);</li></li> <li><li></li></li> <li class="alt"><li class="alt">Btn.setonclicklistener (this<span class="keyword">); </span></li></li> <li><li>}</li></li> <li class="alt"><li class="alt"></li></li> <li><li><span class="annotation">@Override</span></li></li> <li class="alt"><li class="alt"><span class="keyword">public <span class="keyword">void OnClick (View v) {</span> </span></li></li> <li><li><span class="keyword">new Workthread (). start (); </span></li></li> <li class="alt"><li class="alt">}</li></li> <li><li></li></li> <li class="alt"><li class="alt"><span class="comment">//worker Threads</span></li></li> <li><li><span class="keyword">private <span class="keyword">class Workthread <span class="keyword">extends Thread {</span> </span> </span></li></li> <li class="alt"><li class="alt"><span class="annotation">@Override</span></li></li> <li><li><span class="keyword">public <span class="keyword">void run () {</span> </span></li></li> <li class="alt"><li class="alt"><span class="comment">//...... Handle more time-consuming operations</span></li></li> <li><li></li></li> <li class="alt"><li class="alt"><span class="comment">//change status after processing is complete</span></li></li> <li><li>Statetext.settext (<span class="string">"completed"); </span></li></li> <li class="alt"><li class="alt">}</li></li> <li><li>}</li></li> <li class="alt"><li class="alt">}</li></li> </ol><p><p></p></p><p><p>This code seems to look normal, but when you run it you will find that it will report a fatal exception:</p></p><p><p></p></p><strong><strong>[java]</strong></strong>View Plaincopy <ol class="dp-j" start="1"> <ol class="dp-j" start="1"> <li class="alt">Error/androidruntime (<span class="number">421): FATAL exception:thread-<span class="number">8</span> </span></li> <li>Error/androidruntime (<span class="number">421): android.view.viewroot$calledfromwrongthreadexception:</span></li> <li class="alt">Only the original thread, created a view hierarchy can touch its views.</li> </ol> </ol><p><p></p></p><p><p>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.</p></p><p><p>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.</p></p><p><p>Let's modify the above code a little bit:</p></p><p><p></p></p><strong><strong>[java]</strong></strong>View Plaincopy <ol class="dp-j" start="1"> <li class="alt"><li class="alt"><span class="keyword">Public <span class="keyword">class Mainactivity <span class="keyword">extends Activity <span class="keyword">implements View.onclicklistener {</span> </span> </span></span></li></li> <li><li></li></li> <li class="alt"><li class="alt"><span class="keyword">private <span class="keyword">static <span class="keyword">final <span class="keyword">int completed = <span class="number">0; </span></span></span></span></span></li></li> <li><li></li></li> <li class="alt"><li class="alt"><span class="keyword">Private TextView statetext; </span></li></li> <li><li><span class="keyword">Private Button btn; </span></li></li> <li class="alt"><li class="alt"></li></li> <li><li><span class="keyword">private Handler Handler = <span class="keyword">new Handler () {</span> </span></li></li> <li class="alt"><li class="alt"><span class="annotation">@Override</span></li></li> <li><li><span class="keyword">public <span class="keyword">void Handlemessage (Message msg) {</span> </span></li></li> <li class="alt"><li class="alt"><span class="keyword">if (msg.what = = completed) {</span></li></li> <li><li>Statetext.settext (<span class="string">"completed"); </span></li></li> <li class="alt"><li class="alt">}</li></li> <li><li>}</li></li> <li class="alt"><li class="alt">};</li></li> <li><li></li></li> <li class="alt"><li class="alt"><span class="annotation">@Override</span></li></li> <li><li><span class="keyword">public <span class="keyword">void OnCreate (Bundle Savedinstancestate) {</span> </span></li></li> <li class="alt"><li class="alt"><span class="keyword">super.oncreate (savedinstancestate); </span></li></li> <li><li>Setcontentview (r.layout.main);</li></li> <li class="alt"><li class="alt">Statetext = (TextView) Findviewbyid (r.id.tv);</li></li> <li><li>BTN = (Button) Findviewbyid (r.id.btn);</li></li> <li class="alt"><li class="alt"></li></li> <li><li>Btn.setonclicklistener (this<span class="keyword">); </span></li></li> <li class="alt"><li class="alt">}</li></li> <li><li></li></li> <li class="alt"><li class="alt"><span class="annotation">@Override</span></li></li> <li><li><span class="keyword">public <span class="keyword">void OnClick (View v) {</span> </span></li></li> <li class="alt"><li class="alt"><span class="keyword">new Workthread (). start (); </span></li></li> <li><li>}</li></li> <li class="alt"><li class="alt"></li></li> <li><li><span class="comment">//worker Threads</span></li></li> <li class="alt"><li class="alt"><span class="keyword">private <span class="keyword">class Workthread <span class="keyword">extends Thread {</span> </span> </span></li></li> <li><li><span class="annotation">@Override</span></li></li> <li class="alt"><li class="alt"><span class="keyword">public <span class="keyword">void run () {</span> </span></li></li> <li><li><span class="comment">//...... Handle more time-consuming operations</span></li></li> <li class="alt"><li class="alt"></li></li> <li><li><span class="comment">send message to handler after processing is complete</span></li></li> <li class="alt"><li class="alt">Message msg = <span class="keyword">New Message (); </span></li></li> <li><li>Msg.what = completed;</li></li> <li class="alt"><li class="alt">Handler.sendmessage (msg);</li></li> <li><li>}</li></li> <li class="alt"><li class="alt">}</li></li> <li><li>}</li></li> </ol><p><p></p></p><p><p>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.</p></p><p><p>Let's look at the message mechanism in ANDROID.</p></p><p><p>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.</p></p><p><p>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 ().</p></p><p><p>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:</p></p><p><p></p></p><strong><strong>[java]</strong></strong>View Plaincopy <ol class="dp-j" start="1"> <li class="alt"><li class="alt"><span class="keyword">Class Workthread <span class="keyword">extends Thread {</span></span></li></li> <li><li>public <span class="keyword">Handler mhandler; </span></li></li> <li class="alt"><li class="alt"></li></li> <li><li><span class="keyword">public <span class="keyword">void run () {</span> </span></li></li> <li class="alt"><li class="alt">Looper.prepare ();</li></li> <li><li></li></li> <li class="alt"><li class="alt">Mhandler = <span class="keyword">new Handler () {</span></li></li> <li><li><span class="keyword">public <span class="keyword">void Handlemessage (Message msg) {</span> </span></li></li> <li class="alt"><li class="alt"><span class="comment">//processing received Messages</span></li></li> <li><li>}</li></li> <li class="alt"><li class="alt">};</li></li> <li><li></li></li> <li class="alt"><li class="alt">Looper.loop ();</li></li> <li><li>}</li></li> <li class="alt"><li class="alt">}</li></li> </ol><p><p></p></p><p><p>In this way, the worker threads we create have a message handling Mechanism.</p></p><p><p>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.</p></p><p><p>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:</p></p><p><p></p></p><strong><strong>[java]</strong></strong>View Plaincopy <ol class="dp-j" start="1"> <li class="alt"><li class="alt"><span class="comment">/**</span></li></li> <li><li><span class="comment">* Default Constructor Associates This handler with the queue for the</span></li></li> <li class="alt"><li class="alt"><span class="comment">* Current Thread.</span></li></li> <li><li><span class="comment">*</span></li></li> <li class="alt"><li class="alt"><span class="comment">* If there isn ' t one, this handler won ' is able to receive Messages.</span></li></li> <li><li><span class="comment">*/</span></li></li> <li class="alt"><li class="alt">public <span class="keyword">Handler () {</span></li></li> <li><li><span class="keyword">if (find_potential_leaks) {</span></li></li> <li class="alt"><li class="alt"><span class="keyword">Final class<?  <span class="keyword">extends Handler> klass = GetClass (); </span></span></li></li> <li><li><span class="keyword">if (klass.isanonymousclass () | | klass.ismemberclass () | | klass.islocalclass ()) &&</span></li></li> <li class="alt"><li class="alt">(klass.getmodifiers () & modifier.static) = = <span class="number">0) {</span></li></li> <li><li>LOG.W (TAG, <span class="string">"the following Handler class should be static or leaks might occur:" +</span></li></li> <li class="alt"><li class="alt">Klass.getcanonicalname ());</li></li> <li><li>}</li></li> <li class="alt"><li class="alt">}</li></li> <li><li></li></li> <li class="alt"><li class="alt">Mlooper = Looper.mylooper ();</li></li> <li><li><span class="keyword">if (mlooper = = <span class="keyword">Null) {</span> </span></li></li> <li class="alt"><li class="alt"><span class="keyword">throw <span class="keyword">New RuntimeException (</span> </span></li></li> <li><li><span class="string">"Can ' t create handler inside thread that have not called Looper.prepare ()"); </span></li></li> <li class="alt"><li class="alt">}</li></li> <li><li>Mqueue = mlooper.mqueue;</li></li> <li class="alt"><li class="alt">Mcallback = <span class="keyword">null; </span></li></li> <li><li>}</li></li> <li class="alt"><li class="alt"></li></li> <li><li><span class="comment">/**</span></li></li> <li class="alt"><li class="alt"><span class="comment">* Use the provided queue instead of the default One.</span></li></li> <li><li><span class="comment">*/</span></li></li> <li class="alt"><li class="alt">public <span class="keyword">Handler (Looper Looper) {</span></li></li> <li><li>Mlooper = looper;</li></li> <li class="alt"><li class="alt">Mqueue = looper.mqueue;</li></li> <li><li>Mcallback = <span class="keyword">null; </span></li></li> <li class="alt"><li class="alt">}</li></li> </ol><p><p></p></p><p><p>Here is a diagram of several important members of the messaging mechanism:</p></p><p><p></p></p><p><p></p></p><p><p>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.</p></p><p><p>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.</p></p><p><p>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.</p></p><p><p>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.</p></p><p><p>A brief analysis of the message mechanism in Android</p></p></span>
Related Article

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.