Android asynchronous processing 1: Using Thread + Handler to update the UI by using non-UI threads

Source: Internet
Author: User

Overview: Every Android application runs in a dalvik virtual machine process. When a process starts, a main thread (MainThread) is started. The main thread is responsible for processing ui-related events, therefore, the main thread is often called the UI thread. Because Android uses a single-threaded UI model, you can only operate the UI elements in the main thread. If you operate the UI directly in a non-UI thread, an error is returned:
CalledFromWrongThreadException: only the original thread that created a view hierarchy can touch its views
.
Android provides a message loop mechanism. We can use this mechanism to implement inter-thread communication. Then, we can send messages to the UI thread in a non-UI thread, and finally let the Ui thread perform ui operations.
For operations and IO operations that require a large amount of computing, we need to open a new thread to handle these heavy tasks to avoid blocking the ui thread.
Example: The following example shows how to use Thread + Handler to send a message to the UI Thread to update a message in a non-UI Thread.
ThradHandlerActivity. java:
01 public class ThreadHandlerActivity extends Activity {
02/** Called when the activity is first created .*/
03
04 private static final int MSG_SUCCESS = 0; // ID of the image that has been obtained successfully
05 private static final int MSG_FAILURE = 1; // ID of the failed Image Retrieval
06
07 private ImageView mImageView;
08 private Button mButton;
09
10 private Thread mThread;
11
12 private Handler mHandler = new Handler (){
13 public void handleMessage (Message msg) {// This method runs in the ui thread
14 switch (msg. what ){
15 case MSG_SUCCESS:
16 mImageView. setImageBitmap (Bitmap) msg. obj); // imageview displays the logo obtained from the network
17 Toast. makeText (getApplication (), getApplication (). getString (R. string. get_pic_success), Toast. LENGTH_LONG). show ();
18 break;
19
20 case MSG_FAILURE:
21 Toast. makeText (getApplication (), getApplication (). getString (R. string. get_pic_failure), Toast. LENGTH_LONG). show ();
22 break;
23}
24}
25 };
26
27 @ Override
28 public void onCreate (Bundle savedInstanceState ){
29 super. onCreate (savedInstanceState );
30 setContentView (R. layout. main );
31 mImageView = (ImageView) findViewById (R. id. imageView); // display the ImageView of the image
32 mButton = (Button) findViewById (R. id. button );
33 mButton. setOnClickListener (new OnClickListener (){
34
35 @ Override
36 public void onClick (View v ){
37 if (mThread = null ){
38 mThread = new Thread (runnable );
39 mThread. start (); // thread startup
40}
41 else {
42 Toast. makeText (getApplication (), getApplication (). getString (R. string. thread_started), Toast. LENGTH_LONG). show ();
43}
44}
45 });
46}
47
48 Runnable runnable = new Runnable (){
49
50 @ Override
51 public void run () {// run () run in the new thread
52 HttpClient hc = new DefaultHttpClient ();
53 HttpGet hg = new HttpGet ("http://csdnimg.cn/www/images/csdnindex_logo.gif"); // get the csdn logo
54 final Bitmap bm;
55 try {
56 HttpResponse hr = hc.exe cute (hg );
57 bm = BitmapFactory. decodeStream (hr. getEntity (). getContent ());
58} catch (Exception e ){
59 mHandler. obtainMessage (MSG_FAILURE). sendToTarget (); // An error occurred while obtaining the image.
60 return;
61}
62 mHandler. obtainMessage (MSG_SUCCESS, bm). sendToTarget (); // The image is obtained successfully and MSG_SUCCESS ID and bitmap object are sent to the ui thread.
63
64 // mImageView. setImageBitmap (bm); // error! You cannot operate the ui element in a non-ui thread.
65
66 // mImageView. post (new Runnable () {// another more concise method for sending messages to the ui thread.
67 //
68 // @ Override
69 // public void run () {// run () method will be executed in the ui thread
70 // mImageView. setImageBitmap (bm );
71 //}
72 //});
73}
74 };
75
76}

Main. xml layout file:
1 <? Xml version = "1.0" encoding = "UTF-8"?>
2 <LinearLayout xmlns: android = "http://schemas.android.com/apk/res/android"
3 android: orientation = "vertical" android: layout_width = "fill_parent"
4 android: layout_height = "fill_parent">
5 <Button android: id = "@ + id/button" android: text = "@ string/button_name" android: layout_width = "wrap_content" android: layout_height = "wrap_content"> </Button>
6 <ImageView android: id = "@ + id/imageView" android: layout_height = "wrap_content"
7 android: layout_width = "wrap_content"/>
8 </LinearLayout>

Strings. xml
1 <? Xml version = "1.0" encoding = "UTF-8"?>
2 <LinearLayout xmlns: android = "http://schemas.android.com/apk/res/android"
3 android: orientation = "vertical" android: layout_width = "fill_parent"
4 android: layout_height = "fill_parent">
5 <Button android: id = "@ + id/button" android: text = "@ string/button_name" android: layout_width = "wrap_content" android: layout_height = "wrap_content"> </Button>
6 <ImageView android: id = "@ + id/imageView" android: layout_height = "wrap_content"
7 android: layout_width = "wrap_content"/>
8 </LinearLayout>


Manifest. xml:
01 <? Xml version = "1.0" encoding = "UTF-8"?>
02 <manifest xmlns: android = "http://schemas.android.com/apk/res/android"
03 package = "com. zhuozhuo"
04 android: versionCode = "1"
05 android: versionName = "1.0" type = "codeph" text = "/codeph">
06 <uses-sdk android: minSdkVersion = "9"/>
07 <uses-permission android: name = "android. permission. INTERNET"> </uses-permission> <! -- Do not forget to set Network Access Permissions -->
08
09 <application android: icon = "@ drawable/icon" android: label = "@ string/app_name">
10 <activity android: name = ". ThreadHandlerActivity"
11 android: label = "@ string/app_name">
12 <intent-filter>
13 <action android: name = "android. intent. action. MAIN"/>
14 <category android: name = "android. intent. category. LAUNCHER"/>
15 </intent-filter>
16 </activity>
17
18 </application>
19 </manifest>


Running result:
 
 

 
To avoid blocking the ui thread, we use mThread to obtain the csdn logo from the network.
And uses the bitmap object to store the pixel information of the Logo.
At this point, if you call
1 mImageView. setImageBitmap (bm)
 
The following error occurs: CalledFromWrongThreadException: only the original thread that created a view hierarchy can touch its views. The reason is that the run () method is executed in the new thread. We mentioned above that the ui element cannot be operated directly in a non-ui thread.
There are two steps for a non-UI thread to send messages to the UI thread.
1. send messages to the Message Queue of the UI thread
By using Handler's
1 Message obtainMessage (int what, Object object)

Construct a Message object, which stores the IDs of what and bitmap objects for obtaining images successfully. Then, use the message. sendToTarget () method to put the message in the Message queue.
Ii. process messages sent to the UI thread
In the ui thread, We overwrite
1 public void handleMessage (Message msg)
This method is used to process messages distributed to the ui thread and determine msg. the value of what indicates whether mThread has successfully obtained the image. If the image has been obtained successfully, you can use msg. obj gets this object.
Finally, we use
1 mImageView. setImageBitmap (Bitmap) msg. obj );
Set the bitmap object of the ImageView to complete the UI update.


Supplement:
In fact, we can also call
View post method to update the ui
1 mImageView. post (new Runnable () {// another more concise method for sending messages to the ui thread.
2
3 @ Override
4 public void run () {// run () method will be executed in the ui thread
5 mImageView. setImageBitmap (bm );
6}
7 });

This method will send the Runnable object to the message queue, and the ui thread will execute this runnable object after receiving the message.
In the example, we can see that handler has both the function of sending and processing messages, and mistakenly thinks that handler implements message loop and message distribution. In fact, Android makes our code look more concise, to interact with the UI thread, you only need to use the handler object created in the UI thread. For more information about the implementation of the message loop mechanism, see Android asynchronous processing 3: Handler + logoff + MessageQueue.


From lzc's column

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.