Handler usage in Android

Source: Internet
Author: User

Handler usage in Android

In Android development, we often encounter the following situation: After performing an operation on the UI interface, we need to execute a very time-consuming code, for example, if we click a "Download" button on the interface, we need to execute a network request. This is a time-consuming operation because we do not know when to complete it. To ensure that the UI thread is not affected, we will create a new thread to execute our time-consuming code. When our time-consuming operations are completed, We need to update the UI to inform the user that the operations are completed. Therefore, we may write the following code:

Package ispring.com. testhandler; import android. app. activity; import android. OS. bundle; import android. view. view; import android. widget. button; import android. widget. textView; public class MainActivity extends Activity implements Button. onClickListener {private TextView 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 = new DownloadThread (); downloadThread. start ();} class DownloadThread extends Thread {@ Override public void run () {try {System. out. println (start to download the file); // set the Thread DownloadThread to sleep for 5 seconds to simulate the time-consuming process of the file Thread. sleep (1, 5000); System. out. println (File Download completed); // update the UI MainActivity after the file is downloaded. this. statusTextView. setText (File Download completed);} catch (InterruptedException e) {e. printStackTrace ();}}}}

The code above demonstrates that clicking the "Download" button will start a new thread to execute the actual download operation. After the execution is complete, the UI is updated. However, when the Code MainActivity. this. statusTextView. setText ("file download completed") is actually run, the following error is reported. The system crashes and exits:
Android. view. ViewRootImpl $ CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
The error indicates that only the original thread that created the View can update the View. This error occurs because the View in Android is NOT thread-safe. When the Android Application Starts, a thread is automatically created, that is, the main thread of the program, the main thread is responsible for displaying the UI and dispatching and processing the UI event messages. Therefore, the main thread is also called the UI thread, and statusTextView is created in the UI thread, when we update the statusTextView created in the UI thread in the DownloadThread thread, the above error will naturally be reported. Android UI controls are non-thread-safe. In fact, many platform UI controls are non-thread-safe, such as C. the UI controls in the. Net Framework are also non-thread-safe. Therefore, not only does the Android platform have the problem of updating the UI controls created in the UI thread from a new thread. Different platforms provide different solutions to implement cross-thread and new UI controls. Android introduces the Handler mechanism to solve this problem. In fact, Handler can do more things. Handler is a multi-thread communication mechanism introduced in Android, updating the UI control in the UI thread in another thread is only a typical case in Handler usage. In addition, Handler can do many other things. Each Handler is bound to a thread. Suppose there are two threads ThreadA and ThreadB, and HandlerA is bound to ThreadA. For some reason, when the code in ThreadB is executed somewhere, we need ThreadA to execute some code. Now we can use Handler. We can add some information to HandlerA in ThreadB to inform ThreadA of some processing. As we can see, Handler is the spokesperson of Thread and a bridge between multiple threads. With Handler, we can control another Thread in one Thread to do something.
Handler provides two methods to solve the above problem. One is to use the post method and the other is to call the sendMessage method.

A. Use the post method. The Code is as follows:

Package ispring.com. testhandler; import android. app. activity; import android. OS. bundle; import android. OS. handler; import android. view. view; import android. widget. button; import android. widget. textView; public class MainActivity extends Activity implements Button. onClickListener {private TextView statusTextView = null; // uiHandler is created in the main thread, so the main thread private Handler uiHandler = new Handler () is automatically bound; @ 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 = new DownloadThread (); downloadThread. start ();} class DownloadThread extends Thread {@ Override public void run () {try {System. out. println (DownloadThread id + Thread. currentThread (). getId (); System. out. println (start to download the file); // set the Thread DownloadThread to sleep for 5 seconds to simulate the time-consuming process of the file Thread. sleep (1, 5000); System. out. println (File Download completed); // update UI Runnable runnable = new Runnable () {@ Override public void run () {System. out. println (Runnable thread id + Thread. currentThread (). getId (); MainActivity. this. statusTextView. setText (File Download completed) ;}}; uiHandler. post (runnable);} catch (InterruptedException e) {e. printStackTrace ();}}}}

We created a Handler member variable uiHandler in the Activity. Handler has a special feature. When executing new Handler (), Handler binds the thread for executing the current Code by default, uiHandler is instantiated in the main thread, so uiHandler is automatically bound to the main thread, that is, the UI thread. After executing the time-consuming code in DownloadThread, we pass a Runnable object to Handler through the post method. Handler will let the main thread execute the code in Runnable when appropriate, in this way, Runnable runs in the main thread and correctly updates the UI in the main thread. The output result is as follows:

The output results show that the thread ID of the Code in Runnable is different from the thread ID of DownloadThread, and is the same as the thread ID of the main thread. Therefore, Handler is executed. pZ success? Http://www.bkjia.com/kf/ware/vc/ "target =" _ blank "class =" keylink "> vc3qounvubmfiber gup1ek + keys + sLrtcTP37PM0 + tIYW5kbGVyy/keys + keys" brush: java; ">Package ispring.com. testhandler; import android. app. activity; import android. OS. bundle; import android. OS. handler; import android. OS. message; import android. view. view; import android. widget. button; import android. widget. textView; public class MainActivity extends Activity implements Button. onClickListener {private TextView statusTextView = null; // uiHandler is created in the main thread, so it is automatically bound to the main thread private Handler uiHandler = new Handler () {@ 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 = new DownloadThread (); downloadThread. start ();} class DownloadThread extends Thread {@ Override public void run () {try {System. out. println (DownloadThread id + Thread. currentThread (). getId (); System. out. println (start to download the file); // set the Thread DownloadThread to sleep for 5 seconds to simulate the time-consuming process of the file Thread. sleep (1, 5000); System. out. println (File Download completed); // After the file is downloaded, the UI Message msg = new Message () is updated; // although the Message constructor is public, we can also use the following two methods to obtain Message/msg = Message through the cyclic object. obtain (uiHandler); // msg = uiHandler. obtainMessage (); // what is a custom Message identifier, so that different messages can be identified based on what in the handleMessage method of Handler, so that we can make different processing operations msg. what = 1; // we can pass in simple data msg to Message through arg1 and arg2. arg1 = 123; msg. arg2 = 321; // We can also pass any data to the Message by assigning the Object type to obj. // msg. obj = null; // You can also use the setData and getData methods to write and read Bundle-type data to and from the Message. // msg. setData (null); // Bundle data = msg. getData (); // send the Message to the corresponding Handler uiHandler. sendMessage (msg);} catch (InterruptedException e) {e. printStackTrace ();}}}}

To communicate with Handler through Message, follow these steps:
1. Override the handleMessage method of Handler and perform different processing operations based on the value of the Message
2. Create a Message object
Although the Message constructor is public, we can also use Message. obtain () or Handler. obtainMessage () to obtain a Message object (Handler. the obtainMessage () actually calls the Message. obtain ()).
3. Set the value of Message
Message. what is our custom Message identifier, so that we can identify different messages in the handleMessage method of Handler, so that we can make different processing operations.
4. Set the data carried by the Message. Simple data can be assigned values through two int-type field arg1 and arg2, and can be read in handleMessage.
5. If the Message needs to carry complex data, you can set the obj field of the Message. obj is of the Object type and can assign any type of data. Alternatively, you can call the setData method of the Message to assign values to the Bundle type data, and you can use the getData method to obtain the Bundle data.
6. We pass the Message to Handler through the Handler. sendMessage (Message) method so that it can be processed in handleMessage.
It should be noted that, if you do not need to judge the Message Type in handleMessage, you do not need to set the value of Message; and it is not necessary to make the Message carry data, data must be carried only when necessary. If the Message must carry data, use arg1, arg2, or both as much as possible. If arg1 and arg2 can be used, do not use obj, because arg1 and arg2 are more efficient.
The program running result is as follows:
In Android, how to use Handler is introduced. Later, I will write an article to describe the internal implementation principle of Handler, including logoff and MessageQueue.

 

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.