Use of handler in Android

Source: Internet
Author: User
Tags message queue

In Android development, we often encounter a situation where we have to run a very time-consuming code after doing something on the UI, for example, if we click on a "Download" button on the interface, then we need to run the network request, which is a time-consuming operation. Because I do not know when the ability to complete. To ensure that the UI thread is not affected, we create a new thread to run 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 may write code such as the following:

 PackageIspring.com.testhandler;Importandroid.app.Activity;ImportAndroid.os.Bundle;ImportAndroid.view.View;ImportAndroid.widget.Button;ImportAndroid.widget.TextView; Public  class mainactivity extends Activity implements Button. Onclicklistener {    PrivateTextView Statustextview =NULL;@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (R.layout.activity_main);        Statustextview = (TextView) Findviewbyid (R.id.statustextview);        Button Btndownload = (button) Findviewbyid (r.id.btndownload); Btndownload.setonclicklistener ( This); }@Override     Public void OnClick(View v) {Downloadthread Downloadthread =NewDownloadthread ();    Downloadthread.start (); } class Downloadthread extends thread{@Override         Public void Run() {Try{System.out.println ("Start download File");///Here Let the thread Downloadthread hibernate for 5 seconds, the time-consuming process of simulating the fileThread.Sleep ( the); System.out.println ("File Download Complete");//Update UI after file download is completeMainactivity. This. Statustextview.settext ("File Download Complete"); }Catch(Interruptedexception e)            {E.printstacktrace (); }        }    }}

The code above demonstrates that clicking the "Download" button will start a new thread to run the actual download operation. Update the UI interface when you are finished running.

However, when actually running to code MainActivity.this.statusTextView.setText ("File Download Complete"), the error will be as follows. System crashes exiting:
Android.view.viewrootimpl$calledfromwrongthreadexception:only the original thread that created a view hierarchy can Touc H its Views.
The error means that only the original thread that created the view has the ability to update the view. This error occurs because view in Android is not thread-safe. When the Android app starts, it takes its own initiative to create a thread, the program's main thread, which is responsible for UI presentation, UI event message handing, and so on, so the main thread is also called the UI thread, and Statustextview is created in the UI thread. This error is naturally reported when we go to update the Statustextview created in the UI thread in the Downloadthread thread.

Android UI controls are non-thread-safe, and in fact very many platform UI controls are non-thread-safe, for example, UI controls in the. Net framework of C # are also not thread-safe. 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 such problems.

So what exactly is handler? Handler is a mechanism introduced in Android that allows developers to participate in the processing of message loops in threads. Each hanlder is associated with a thread, and each thread maintains a Message Queuing MessageQueue inside, so that handler actually associates a message queue. The ability to send message and runnable objects through handler to the MessageQueue (Message queue) of the thread associated with the handler. The message queue then takes out a message in a loop, processes it, takes out the next message after processing, and continues processing. Cycle. When a handler is created, the handler binds the thread that is currently creating the Hanlder. From this point on, the Hanlder is able to send the message and the Runnable object to the handler corresponding messages queue. When a message is removed from MessageQueue. Will let the handler deal with it.

Handler can be used to communicate between multiple threads, and a UI control in a thread that updates the UI thread is only a typical case of handler use. Besides, handler can do a lot of other things. Each of the handler is bound to a thread. Suppose there are two threads Threada and threadb. And Handlera binds Threada, when the code in THREADB runs somewhere, for some reason, we need to let Threada run some code, and we can use handler at this point. We were able to add some information to the Handlera in threadb to inform Threada that some processing should be done.

From this we can see that handler is the spokesperson of thread. is a bridge of communication between multiple threads, through handler, we are able to control a thread in one thread to do something.

Handler provides two ways to solve the problem we encountered at the beginning of this article (updating UI controls in the main thread in a new one), one through the post method, and one called the SendMessage method.

A. Use the Post method. The code is as follows:

 PackageIspring.com.testhandler;Importandroid.app.Activity;ImportAndroid.os.Bundle;ImportAndroid.os.Handler;ImportAndroid.view.View;ImportAndroid.widget.Button;ImportAndroid.widget.TextView; Public  class mainactivity extends Activity implements Button . Onclicklistener {    PrivateTextView Statustextview =NULL;//uihandler is created in the main thread, so you actively bind the main thread    PrivateHandler Uihandler =NewHandler ();@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (R.layout.activity_main);        Statustextview = (TextView) Findviewbyid (R.id.statustextview);        Button Btndownload = (button) Findviewbyid (r.id.btndownload); Btndownload.setonclicklistener ( This); System.out.println ("Main thread id"+ Thread.CurrentThread (). GetId ()); }@Override     Public void OnClick(View v) {Downloadthread Downloadthread =NewDownloadthread ();    Downloadthread.start (); } class Downloadthread extends thread{@Override         Public void Run() {Try{System.out.println ("Downloadthread id"+ Thread.CurrentThread (). GetId ()); System.out.println ("Start download File");///Here Let the thread downloadthread dormant for 5 seconds. The time-consuming process of simulating filesThread.Sleep ( the); System.out.println ("File Download Complete");//Update UI after file download is completeRunnable Runnable =NewRunnable () {@Override                     Public void Run() {System.out.println ("Runnable thread id"+ Thread.CurrentThread (). GetId ()); Mainactivity. This. Statustextview.settext ("File Download Complete");                }                };            Uihandler.post (runnable); }Catch(Interruptedexception e)            {E.printstacktrace (); }        }    }}

We created a handler member variable in activity Uihandler,handler has a feature. When running new Handler (), by default Handler binds the thread that the current code is running, and we instantiate the Uihandler in the main thread, so Uihandler is actively binding the main thread, the UI thread. When we run out of time-consuming code in Downloadthread. We pass a Runnable object through the Post method into the handler, handler will let the main thread run the code in runnable at the appropriate time, so runnable is running in the main thread, thus correctly updating the UI in the main thread. The following is the output result:

Can be seen by the output results. The code in Runnable runs with a different thread ID than the thread ID of downloadthread, and the thread ID of the main threads is the same, so we see that after running the code of Handler.post (Runnable), The thread that runs the Runnable code is consistent with the thread that handler is bound to, regardless of the thread (Downloadthread) that runs the code for Handler.post (Runnable).

B. Using the SendMessage method, code such as the following:

 PackageIspring.com.testhandler;Importandroid.app.Activity;ImportAndroid.os.Bundle;ImportAndroid.os.Handler;ImportAndroid.os.Message;ImportAndroid.view.View;ImportAndroid.widget.Button;ImportAndroid.widget.TextView; Public  class mainactivity extends Activity implements Button. Onclicklistener {    PrivateTextView Statustextview =NULL;//uihandler is created in the main thread, so you actively bind the main thread    PrivateHandler Uihandler =NewHandler () {@Override         Public void Handlemessage(Message msg) {Switch(Msg.what) { Case 1: System.out.println ("Handlemessage thread id"+ Thread.CurrentThread (). GetId ()); System.out.println ("MSG.ARG1:"+ MSG.ARG1); System.out.println ("MSG.ARG2:"+ msg.arg2); Mainactivity. This. Statustextview.settext ("File Download Complete"); Break; }        }    };@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (R.layout.activity_main);        Statustextview = (TextView) Findviewbyid (R.id.statustextview);        Button Btndownload = (button) Findviewbyid (r.id.btndownload); Btndownload.setonclicklistener ( This); System.out.println ("Main thread id"+ Thread.CurrentThread (). GetId ()); }@Override     Public void OnClick(View v) {Downloadthread Downloadthread =NewDownloadthread ();    Downloadthread.start (); } class Downloadthread extends thread{@Override         Public void Run() {Try{System.out.println ("Downloadthread id"+ Thread.CurrentThread (). GetId ()); System.out.println ("Start download File");///Here Let the thread downloadthread dormant for 5 seconds. The time-consuming process of simulating filesThread.Sleep ( the); System.out.println ("File Download Complete");//Update UI after file download is completeMessage msg =NewMessage ();//Although the constructor of message is public, we are able to get a message through the Loop object in the following two ways                //msg = Message.obtain (Uihandler);                //msg = Uihandler.obtainmessage ();                //what is the identification code of a message that we define ourselves. Based on what is identified in the Handlemessage method of the handler                //out of a different message. So that we can make different processing operations.Msg.what =1;//We can pass simple data to a message via Arg1 and Arg2MSG.ARG1 =123; MSG.ARG2 =321;//We are also able to pass arbitrary data to a message by assigning an object type to obj                //msg.obj = null;                //We are also able to write and read bundle type data to message through the SetData method and the GetData method                //msg.setdata (null);                //bundle data = Msg.getdata ();                //Send the message to the appropriate handlerUihandler.sendmessage (msg); }Catch(Interruptedexception e)            {E.printstacktrace (); }        }    }}

The steps to communicate with handler through a message are:
1. Override Handler's Handlemessage method to perform different processing operations based on what value of message
2. Create a Message object
Although the constructor of the message is public, we can also get a Message object (Handler.obtainmessage () by Message.obtain () or handler.obtainmessage () The Message.obtain () is actually called inside.
3. Set the what value of the message
Message.what is the identifier of a message that we define for ourselves so that we can identify different message based on what in the handler Handlemessage method. So that we can make different processing operations.
4. Set the data that is carried by the message. Simple data can be assigned with field Arg1 and arg2 of two int types. And can be read in Handlemessage.
5. Assuming that the message needs to carry complex data, the obj field of the message can be set, and obj is the object type that can give arbitrary types of data. Or you can assign the data of bundle type by invoking the SetData method of message, which can get the bundle data through the GetData method.
6. We pass a message into the handler through the Handler.sendmessage (message) method so that it is processed in handlemessage.
It is important to note that if you do not need to infer the message type in Handlemessage, you do not need to set the what value of the message, and it is not necessary to have the message carry the data, only need it to carry the data when it is needed. ; Suppose you do need to have the message carry data, try to use arg1 or arg2 or both. You can use Arg1 and arg2 to solve the words do not use obj, because with arg1 and arg2 more efficient.
The running results of the program are as follows:

From the above we can see. The thread running Handlemessage is the same thread as the thread that created the handler, which is the main thread in this demo sample.

The thread running Handlemessage is not related to the thread running Uihandler.sendmessage (msg).

This article is mainly about the role of handler in Android, how to use the preliminary introduction, assuming you want to understand the handler internal implementation principle, can see the next blog "Deep source code to resolve the Handler,message in Android, Messagequeue,looper ".

Use of handler in Android

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.