Use of handler in Android

Source: Internet
Author: User
<span id="Label3"></p><p><p>In Android development, we often encounter a situation where a time-consuming code is executed after doing something on the UI interface, such as when we click on a "download" button on the interface, then we need to execute a network request, which is a time-consuming operation because we do not know when to complete it. To ensure that the UI thread is not affected, we create a new thread to execute our time-consuming code. When our time-consuming operation is complete, we need to update the UI interface to inform the user that the operation is Complete. So we might write the following code:</p></p><pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword"><span class="hljs-keyword"></span> package</span>ispring.com.testhandler;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.app.Activity;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.os.Bundle;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.view.View;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.widget.Button;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.widget.TextView;<span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-class"><span class="hljs-class"> <span class="hljs-keyword">class</span> <span class="hljs-title">mainactivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Activity</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Button</span>. <span class="hljs-title">Onclicklistener</span> {</span></span> <span class="hljs-keyword"><span class="hljs-keyword">Private</span></span>TextView Statustextview =<span class="hljs-keyword"><span class="hljs-keyword">NULL</span></span>;<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword">protected</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">onCreate</span></span>(Bundle Savedinstancestate) {<span class="hljs-keyword"><span class="hljs-keyword">Super</span></span>. onCreate (savedinstancestate); Setcontentview (r.layout.activity_main); Statustextview = (TextView) Findviewbyid (r.id.statustextview); Button Btndownload = (button) Findviewbyid (r.id.btndownload); Btndownload.setonclicklistener (<span class="hljs-keyword"><span class="hljs-keyword"></span> this</span>); }<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">OnClick</span></span>(View V) {downloadthread Downloadthread =<span class="hljs-keyword"><span class="hljs-keyword">New</span></span>Downloadthread (); Downloadthread.start (); } class Downloadthread extends thread{<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">Run</span></span>() {<span class="hljs-keyword"><span class="hljs-keyword">Try</span></span>{System.out.println (<span class="hljs-string"><span class="hljs-string">"start Download file"</span></span>);<span class="hljs-comment"><span class="hljs-comment">///here Let the thread Downloadthread hibernate for 5 seconds, the time-consuming process of simulating the file</span></span>Thread.Sleep (<span class="hljs-number"><span class="hljs-number"></span> the</span>); System.out.println (<span class="hljs-string"><span class="hljs-string">"file Download complete"</span></span>);<span class="hljs-comment"><span class="hljs-comment">//update ui after file download is complete</span></span>Mainactivity.<span class="hljs-keyword"><span class="hljs-keyword"></span> this</span>. Statustextview.settext (<span class="hljs-string"><span class="hljs-string">"file Download complete"</span></span>); }<span class="hljs-keyword"><span class="hljs-keyword">Catch</span></span>(interruptedexception E) {e.printstacktrace (); } } }}</code></pre><p>The above code demonstrates that clicking the Download button launches a new thread to perform the actual download operation and updates the UI interface after the execution is Complete. however, when actually running to code MainActivity.this.statusTextView.setText ("file download complete"), the error is as follows, the system crashes and exits:<br>Android.view.viewrootimpl$calledfromwrongthreadexception:only the original thread that created a view hierarchy can Touc H its Views.<br>The error means that only the original thread that created the view can update the VIEW. The reason for this error is that the view in Android is not thread-safe, and when the Android app starts, it automatically creates a thread that is called the main thread of the program, the main thread is responsible for the UI presentation, the UI event message is distributed, and so on, so the main thread is also known as the UI Thread. Statustextview is created in the UI thread, and when we update the Statustextview created in the UI thread in the Downloadthread thread, we will naturally report the above Error. Android UI controls are non-thread-safe, but many platform UI controls are non-thread-safe, such as UI controls in The. Net framework of C #. So not only is there an issue in the Android platform to update UI controls created in the UI thread from a new thread. Different platforms provide different solutions to implement cross threading with new UI controls, and Android has introduced the handler mechanism in order to solve this problem. In fact, handler can do more things, handler is introduced in Android a multi-threaded communication mechanism, in another thread to update UI control in the UI thread is just a typical case in handler use, in addition, handler can do a lot of other things. Each handler is bound to a thread, assuming there are two threads Threada and threadb, and Handlera bound threada, where the code in THREADB executes somewhere, for some reason we need to have Threada execute some code, At this point we can use handler, and we can add some information to Handlera in threadb to tell Threada that some processing is DONE. As can be seen, handler is the spokesperson of thread, is a bridge between multi-threaded communication, through handler, we can control another thread in one thread to do something.<br>Handler provides two ways to solve the above problem, one is through the post method, and the other is to call the SendMessage method.</p><p><p>A. Using the post method, the code is as Follows:</p></p><pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword"><span class="hljs-keyword"></span> package</span>ispring.com.testhandler;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.app.Activity;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.os.Bundle;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.os.Handler;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.view.View;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.widget.Button;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.widget.TextView;<span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-class"><span class="hljs-class"> <span class="hljs-keyword">class</span> <span class="hljs-title">mainactivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Activity</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Button </span>. <span class="hljs-title">Onclicklistener</span> {</span></span> <span class="hljs-keyword"><span class="hljs-keyword">Private</span></span>TextView Statustextview =<span class="hljs-keyword"><span class="hljs-keyword">NULL</span></span>;<span class="hljs-comment"><span class="hljs-comment">//uihandler is created in the main thread, so the main thread is automatically bound</span></span> <span class="hljs-keyword"><span class="hljs-keyword">Private</span></span>Handler Uihandler =<span class="hljs-keyword"><span class="hljs-keyword">New</span></span>Handler ();<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword">protected</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">onCreate</span></span>(Bundle Savedinstancestate) {<span class="hljs-keyword"><span class="hljs-keyword">Super</span></span>. onCreate (savedinstancestate); Setcontentview (r.layout.activity_main); Statustextview = (TextView) Findviewbyid (r.id.statustextview); Button Btndownload = (button) Findviewbyid (r.id.btndownload); Btndownload.setonclicklistener (<span class="hljs-keyword"><span class="hljs-keyword"></span> this</span>); System.out.println (<span class="hljs-string"><span class="hljs-string">"Main thread id"</span></span>+ Thread.CurrentThread (). getId ()); }<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">OnClick</span></span>(View V) {downloadthread Downloadthread =<span class="hljs-keyword"><span class="hljs-keyword">New</span></span>Downloadthread (); Downloadthread.start (); } class Downloadthread extends thread{<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">Run</span></span>() {<span class="hljs-keyword"><span class="hljs-keyword">Try</span></span>{System.out.println (<span class="hljs-string"><span class="hljs-string">"downloadthread id"</span></span>+ Thread.CurrentThread (). getId ()); System.out.println (<span class="hljs-string"><span class="hljs-string">"start Download file"</span></span>);<span class="hljs-comment"><span class="hljs-comment">///here Let the thread Downloadthread hibernate for 5 seconds, the time-consuming process of simulating the file</span></span>Thread.Sleep (<span class="hljs-number"><span class="hljs-number"></span> the</span>); System.out.println (<span class="hljs-string"><span class="hljs-string">"file Download complete"</span></span>);<span class="hljs-comment"><span class="hljs-comment">//update ui after file download is complete</span></span>Runnable Runnable =<span class="hljs-keyword"><span class="hljs-keyword">New</span></span>Runnable () {<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">Run</span></span>() {System.out.println (<span class="hljs-string"><span class="hljs-string">"Runnable thread id"</span></span>+ Thread.CurrentThread (). getId ()); Mainactivity.<span class="hljs-keyword"><span class="hljs-keyword"></span> this</span>. Statustextview.settext (<span class="hljs-string"><span class="hljs-string">"file Download complete"</span></span>); } }; Uihandler.post (runnable); }<span class="hljs-keyword"><span class="hljs-keyword">Catch</span></span>(interruptedexception E) {e.printstacktrace (); } } }}</code></pre><p><p>We created a Handler member variable in activity Uihandler,handler has a feature that when you execute new Handler (), by default Handler binds the thread that the current code Executes. We instantiate the Uihandler in the main thread, so Uihandler automatically binds the main thread, the UI Thread. When we execute the time-consuming code in downloadthread, we pass a Runnable object through the Post method into the handler, handler will let the main thread execute the code in runnable at the appropriate Time. This runnable executes in the main thread, thus correctly updating the UI in the main thread. The following are the output results:<br></p></p><p><p>As can be seen from the output, the code in Runnable executes a different thread ID than the thread ID of the downloadthread, and the thread ID of the main threads is the same, so we see that after executing the code of Handler.post (Runnable), The thread that runs the Runnable code is consistent with the thread that the handler binds to, regardless of the thread (downloadthread) that executes the handler.post (Runnable) Code.</p></p><p><p>B. Using the SendMessage method, the code is as Follows:</p></p><pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword"><span class="hljs-keyword"></span> package</span>ispring.com.testhandler;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.app.Activity;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.os.Bundle;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.os.Handler;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.os.Message;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.view.View;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.widget.Button;<span class="hljs-keyword"><span class="hljs-keyword">Import</span></span>android.widget.TextView;<span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-class"><span class="hljs-class"> <span class="hljs-keyword">class</span> <span class="hljs-title">mainactivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Activity</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Button</span>. <span class="hljs-title">Onclicklistener</span> {</span></span> <span class="hljs-keyword"><span class="hljs-keyword">Private</span></span>TextView Statustextview =<span class="hljs-keyword"><span class="hljs-keyword">NULL</span></span>;<span class="hljs-comment"><span class="hljs-comment">//uihandler is created in the main thread, so the main thread is automatically bound</span></span> <span class="hljs-keyword"><span class="hljs-keyword">Private</span></span>Handler Uihandler =<span class="hljs-keyword"><span class="hljs-keyword">New</span></span>Handler () {<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">Handlemessage</span></span>(Message Msg) {<span class="hljs-keyword"><span class="hljs-keyword">Switch</span></span>(msg.what) {<span class="hljs-keyword"><span class="hljs-keyword"></span> case</span> <span class="hljs-number"><span class="hljs-number">1</span></span>: System.out.println (<span class="hljs-string"><span class="hljs-string">"handlemessage thread id"</span></span>+ Thread.CurrentThread (). getId ()); System.out.println (<span class="hljs-string"><span class="hljs-string">"msg.arg1:"</span></span>+ msg.arg1); System.out.println (<span class="hljs-string"><span class="hljs-string">"msg.arg2:"</span></span>+ msg.arg2); Mainactivity.<span class="hljs-keyword"><span class="hljs-keyword"></span> this</span>. Statustextview.settext (<span class="hljs-string"><span class="hljs-string">"file Download complete"</span></span>);<span class="hljs-keyword"><span class="hljs-keyword"></span> break</span>; } } };<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword">protected</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">onCreate</span></span>(Bundle Savedinstancestate) {<span class="hljs-keyword"><span class="hljs-keyword">Super</span></span>. onCreate (savedinstancestate); Setcontentview (r.layout.activity_main); Statustextview = (TextView) Findviewbyid (r.id.statustextview); Button Btndownload = (button) Findviewbyid (r.id.btndownload); Btndownload.setonclicklistener (<span class="hljs-keyword"><span class="hljs-keyword"></span> this</span>); System.out.println (<span class="hljs-string"><span class="hljs-string">"Main thread id"</span></span>+ Thread.CurrentThread (). getId ()); }<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">OnClick</span></span>(View V) {downloadthread Downloadthread =<span class="hljs-keyword"><span class="hljs-keyword">New</span></span>Downloadthread (); Downloadthread.start (); } class Downloadthread extends thread{<span class="hljs-annotation"><span class="hljs-annotation">@Override</span></span> <span class="hljs-keyword"><span class="hljs-keyword"></span> public</span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">Run</span></span>() {<span class="hljs-keyword"><span class="hljs-keyword">Try</span></span>{System.out.println (<span class="hljs-string"><span class="hljs-string">"downloadthread id"</span></span>+ Thread.CurrentThread (). getId ()); System.out.println (<span class="hljs-string"><span class="hljs-string">"start Download file"</span></span>);<span class="hljs-comment"><span class="hljs-comment">///here Let the thread Downloadthread hibernate for 5 seconds, the time-consuming process of simulating the file</span></span>Thread.Sleep (<span class="hljs-number"><span class="hljs-number"></span> the</span>); System.out.println (<span class="hljs-string"><span class="hljs-string">"file Download complete"</span></span>);<span class="hljs-comment"><span class="hljs-comment">//update ui after file download is complete</span></span>Message msg =<span class="hljs-keyword"><span class="hljs-keyword">New</span></span>Message ();<span class="hljs-comment"><span class="hljs-comment">//although The constructor of message is public, we can also get a message through the Loop object in the following two ways</span></span> <span class="hljs-comment"><span class="hljs-comment">//msg = Message.obtain (uihandler);</span></span> <span class="hljs-comment"><span class="hljs-comment">//msg = uihandler.obtainmessage ();</span></span> <span class="hljs-comment"><span class="hljs-comment">//what is the identifier of a message that we</span> have customized so that it can be identified in the Handlemessage method of the handler</span> <span class="hljs-comment"><span class="hljs-comment">//out of different message so that we can make different processing operations</span></span>Msg.what =<span class="hljs-number"><span class="hljs-number">1</span></span>;<span class="hljs-comment"><span class="hljs-comment">//we can pass simple data to a message via Arg1 and Arg2</span></span>MSG.ARG1 =<span class="hljs-number"><span class="hljs-number">123</span></span>; MSG.ARG2 =<span class="hljs-number"><span class="hljs-number">321</span></span>;<span class="hljs-comment"><span class="hljs-comment">//we can also pass in arbitrary data to a message by assigning an object type to obj</span></span> <span class="hljs-comment"><span class="hljs-comment">//msg.obj = null;</span></span> <span class="hljs-comment"><span class="hljs-comment">//we can also write and read bundle type data to message through the SetData method and the GetData method</span></span> <span class="hljs-comment"><span class="hljs-comment">//msg.setdata (null);</span></span> <span class="hljs-comment"><span class="hljs-comment">//bundle data = Msg.getdata ();</span></span> <span class="hljs-comment"><span class="hljs-comment">//send the message to the corresponding handler</span></span>Uihandler.sendmessage (msg); }<span class="hljs-keyword"><span class="hljs-keyword">Catch</span></span>(interruptedexception E) {e.printstacktrace (); } } }}</code></pre><p><p> The steps to communicate with handler through a message are: <br> 1. Override the Handlemessage method of handler to perform different processing operations based on what value of message <br> 2. Create a Message object <br> Although the constructor of the message is public, we can also get a message object (handler.obtainmessage () by Message.obtain () or Handler.obtainmessage (). The interior actually calls Message.obtain ()). <br> 3. Set what value of message <br> Message.what is our custom code for a message that allows us to identify different message types in the handler Handlemessage method, so that we can make different processing operations. <br> 4. Set the data that the message carries, simple data can be assigned by two field arg1 and arg2 of type int, and can be read in Handlemessage. <br> 5. If the message needs to carry complex data, you can set the obj field of the message, and obj is the object type, which can be assigned to any type of Data. Or you can assign data of bundle type by invoking the SetData method of message, which can be obtained by GetData Method. <br> 6. We pass the message through the Handler.sendmessage (message) method into the handler so that it is processed in Handlemessage. <br> It is important to note that if you do not need to determine the message type in handlemessage, then you do not have to set the what value of the message, and it is not necessary to have the message carry data, only need it to carry the data when needed If you do need to let the message carry data, you should try to use arg1 or arg2 or both, if you can solve with arg1 and arg2, do not use obj, because Arg1 and arg2 are more Efficient. The <br> program runs with the following results: <br> </p></p><p><p>As we can see from the above, the thread executing the handlemessage is the same thread as the thread that created the handler, in this case the main thread. The thread executing the handlemessage does not have a relationship with the thread that executes Uihandler.sendmessage (msg).</p></p><p><p>This article is mainly about the role of handler in android, the preliminary introduction of how to use, the following will be written in detail handler of the internal implementation of the principle, including looper, messagequeue, etc.</p></p> <p style="font-size:12px;"><p style="font-size:12px;">Copyright Notice: This article for Bo Master original article, without Bo Master permission not Reproduced.</p></p> <p><p>Use of handler in Android</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.