Android Handler principle

Source: Internet
Author: User
<span id="Label3"></p><p><p><span style="font-size: 16px;"><span style="font-size: 16px;">An asynchronous callback mechanism is provided in Android handler, which allows us to make a notification after a long task has been completed</span></span></p></p><p><p><span style="font-size: 16px;">Handler Basic Use:</span></p></p><p><p><span style="font-size: 16px;">In the main thread, using handler is simple, new a handler object implements its Handlemessage method, in Handlemessage<br>Provide the corresponding processing method after receiving the message, here does not handler the use of detailed explanation, before looking at Ben Boven, the reader should first grasp the basic use of handler, I here mainly in-depth description of handler internal mechanism</span></p></p><p><p><span style="font-size: 16px;">Now we have a problem first, we use Mythreadhandler.sendemptymessage (0); send a message object, So how does handler receive the message object and handle it? Let me draw a data structure diagram:</span></p></p><p><p><span style="font-size: 16px;"></span></p></p><p><p><span style="font-size: 16px;">From this figure we can see that after calling sendemptymessage, the message object is placed in a MessageQueue queue belonging to a looper object, each Looper object passing Threadlocal.set ( New Looper ()) is bound to a thread, The thread that the Looper object belongs to loops through the Looper.loop method, reads the message object from the MessageQueue queue, and puts the message object handler processing, calling Handler's DispatchMessage method.</span></p></p><p><p><span style="font-size: 16px;">Now let's take a look at the basic implementation code that uses Handler:</span></p></p><p><span style="font-size: 16px;">Create a new handler in the main thread<br>Normalhandler = new Handler () {<br>public void Handlemessage (android.os.Message Msg) {<br>Btnsendmsg2normalhandler.settext ("normalhandler");<br>LOG.D (constant.tag, messageformat.format ("thread[{0}]--normalhandler handlemessage run ...", Thread.currentThread ()<br>. GetName ()));<br>}<br>};</span></p><p><p><span style="font-size: 16px;">...<br>Send Message to Hanlder<br>Mythreadhandler.sendemptymessage (0);</span></p></p><p><p><span style="font-size: 16px;">You are now well aware of the process of sendemptymessage to handlemessage, On the way through the Looper.messagequeue queue, transferred by the Looper on the thread to deal with, This is an asynchronous process, of course, Looper is located in the same thread can be sendemptymessage.</span></p></p><p><p><span style="font-size: 16px;">See above you may still be puzzled, then what to looper, with we want to use of handler and what Bird relationship?</span></p></p><p><p><span style="font-size: 16px;">I have always emphasized the use of handler in the main thread, why do you say so, because you in the new thread of your own to build a handler as simple as before, program execution will be error:</span></p></p><p><p><span style="color: #ff0000;"><span style="font-size: 16px;">Java.lang.RuntimeException:Can ' t create handler inside thread that have not called Looper.prepare ()<br>At Android.os.handler.<init> (handler.java:121)<br>At Com.cao.android.demos.handles.handletestactivity$mythread$1.<init> (handletestactivity.java:86)<br>At Com.cao.android.demos.handles.handletestactivity$mythread.run (handletestactivity.java:86)</span></span></p></p><p><p><span style="color: #ff0000;"><span style="font-size: 16px;">Why is there no error in the main thread, and it is reported in the <span style="color: #000000;">Newly-seen threads? Very simple, because the main thread it has established looper, you can open the Activitythread source to See:</span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">public static final void main (string[] Args) {<br>Samplingprofilerintegration.start ();</span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">Process.setargv0 ("<pre-initialized>");</span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;"><span style="color: #ff0000;">Looper.preparemainlooper ();</span></span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">Activitythread thread = new Activitythread ();<br>Thread.attach (false);</span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;"><span style="color: #ff0000;">Looper.loop ();</span></span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">If (process.supportsprocesses ()) {<br>throw new RuntimeException ("Main thread loop unexpectedly exited");<br>}</span></span></span></p></p><p><p> <span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size:16px;">         Thread.detach (); <br>         String name = (thread.minitialapplication! = Null) <br>             ? Thread.mInitialApplication.getPackageName () <br>             : "<unknown>"; <br>         slog.i (TAG, "Main thread of" + name + "is now exiting"); <br>    } </span> </span> </span> </p></p><p><p> <span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size:16px;">     in the main function it has done this thing, why call Looper.preparemainlooper (); Looper.loop (); We can take a look inside. a new Looper object is created in the Preparemainlooper method and is bound to the current process. In the Looper.loop method, the thread establishes a message loop mechanism that loops through the MessageQueue to get the message object, calling   Msg.target.dispatchMessage (msg); The processing Msg.target is set in Mythreadhandler.sendemptymessage (0), because multiple hander can be built in a thead, With Msg.target to ensure that each msg in the MessageQueue is disposed of by the handler that sent the message, how does handler relate to looper, and in the handler constructor there is a code like This: </span> </span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">Mlooper =<span style="font-size: 16px;"> <span style="color: #ff0000;"> looper.mylooper ();<br>if (mlooper = = Null) {<br>throw New RuntimeException (<br>"Can ' t create handler inside thread that have not called Looper.prepare ()");<br>}<br>Mqueue = mlooper.mqueue;</span></span></span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">When you create a new handler, you need to set the Mlooper member, Looper.mylooper is the Looper object that gets the bindings from the current thread:</span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">public static final Looper Mylooper () {<br>return <span style="font-size: 16px;"> <span style="color: #ff0000;">(Looper) sthreadlocal.get ();<br>}</span></span></span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">If the Looper object is not created, it throws an exception to <span style="font-size: 16px;"> <span style="color: #ff0000;">the "can ' t create handler inside thread that have not called Looper.prepare ()"<br>This is consistent with what I said Earlier. So we're going to create a handler in a new thread that needs to be written like this:</span></span></span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">Class MyThread extends Thread {</span></span></span></p></p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">public void Run () {<br>LOG.D (constant.tag, messageformat.format ("thread[{0}]--run ...", Thread<br>. CurrentThread (). GetName ()));<br>Create a new handler in other threads<br> <span style="color: #ff0000;">Looper.prepare ();//<span style="font-size: 16px;"><span style="color: #ff0000;">Create a Looper object for the thread that receives the message, which is not looper in the Non-main thread, so be sure to create a looper before creating handler with prepare ()<br>Mythreadhandler = new Handler () {<br>public void Handlemessage (android.os.Message Msg) {<br>LOG.D (constant.tag, messageformat.format ("thread[{0}]--mythreadhandler handlemessage run ...", Thread<br>. CurrentThread (). GetName ()));<br>}<br>};<br><span style="font-size: 16px;"><span style="font-size: 16px;"> <span style="color: #ff0000;">looper.mylooper (). loop ();//create A message loop that does not exit<br>}<br>}</span></span></span></span></span></span></span></span></span></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">now, you should know something about Handler's mechanism, and if you have any questions, please ask in the Comments.</span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">Handler using the main thread in other threads Looper</span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">I told you Before. to create a new handler in a newer thread, you need to call Looper.prepare (); Another way is to use Looper in the main thread, so you don't have to create a new Looper object:</span></span></span></p></p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">Threadmainloophandler =new Handler (<span style="font-size: 16px;"><span style="color: #ff0000;">Looper.getmainlooper ()) {<br>public void Handlemessage (android.os.Message Msg) {<br>LOG.D (constant.tag, messageformat.format ("thread[{0}]--threadmainloophandler handlemessage run ...", Thread<br>. CurrentThread (). GetName ()));<br>}<br>The Handlemessage method will be executed in the Mainthread<br>};</span></span></span></span></span></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">Be careful not to do too much at Handlemessage because it executes in the main thread, which affects the main thread to perform UI update Operations.</span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">Using the Message.callback callback</span></span></span></p></p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">public void DispatchMessage (Message Msg) {<br>If (msg.callback! = Null) {<br>Handlecallback (msg);<br>} else {<br>If (mcallback! = Null) {<br>If (mcallback.handlemessage (msg)) {<br>Return<br>}<br>}<br>Handlemessage (msg);<br>}<br>}<br>As you can see from the DispatchMessage definition, if the message object comes with a callback object, Handler does not execute the Handlemessage method but executes the run method defined in message.callback, and of course callback is executed in the thread bound by handler associated Looper. In fact Handler.post (Runnable R) method is to add R to a msg.callback, that is to say, the following two ways of writing, there is no difference:</span></span></span></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">1. Using Message.callback</span></span></span></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">message msg = message.obtain (mythreadhandler,<span class="keyword">new runnable ()  {   </span> </li> <li>        </li> <li class="alt">    <span class="annotation"> @Override    </span> </li> <li>     <span class="keyword">public <span class="keyword">void run ()  {    </span> </span> </li> <li class="alt">        log.d (constant.tag,  messageformat.format (<span class="string"> "thread[{0}]--mythreadhandler.message.callback.run",    </span> </li> <li>                  thread.currentthread (). getName ());     </li> <li class="alt">     }   </li> <li>});    </li> <li class="alt">mythreadhandler.sendmessage (msg);    </li> </ol> </ol><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">2. Using Handler.post</span></span></span></p></p><p><p>http://blog.csdn.net/stonecao/article/details/6417364</p></p><strong><strong>[java]</strong></strong>View Plaincopy <ol class="dp-j" start="1"> <li class="alt"><li class="alt">Mythreadhandler.post (<span class="keyword">new Runnable () {</span></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 run () {</span> </span></li></li> <li class="alt"><li class="alt">LOG.D (constant.tag, Messageformat.format (<span class="string">"thread[{0}]--mythreadhandler.message.callback.run",</span></li></li> <li><li>Thread.CurrentThread (). GetName ());</li></li> <li class="alt"><li class="alt">}</li></li> <li><li>});</li></li> </ol><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">Note: for the handler mechanism-related tests, I wrote a test class:</span></span></span></p></p><p><p><span style="color: #ff0000;"><span style="color: #000000;"><span style="font-size: 16px;">http://download.csdn.net/source/3275970</span></span></span></p></p><p><p><span style="font-size: 16px;">3.Handler effect on activity Finish.</span></p></p><p><p><span style="font-size: 16px;">In the process of development encountered a difficult problem, Call the Activity.finish function acitivity does not perform the ondestory function of the life cycle, after looking for half a day because there is a handler member because it has a delay message is not processed, call activity.finish,activity will not immediately de story, so remember to clean up the handle before ativity finish, so the activity will go smoothly destory</span></p></p><p><p>Android Handler principle</p></p></span>

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.