Android asynchronous processing one: using Thread+handler to implement non-UI thread update UI interface
Overview : Each Android application runs in a Dalvik virtual machine process, where the process starts with a main thread (Mainthread) that handles and UI-related events, so the main thread is often called the UI thread. Because Android uses the UI single-threaded model, the UI elements can only be manipulated in the main thread. If the UI is directly manipulated on a non-UI thread, an error is made:
Calledfromwrongthreadexception:only the original thread that created a view hierarchy can touch it views
。
Android provides us with a mechanism for message loops that we can use to implement communication between threads. Then we can send a message to the UI thread in a non-UI thread, and eventually let the UI thread do the UI.
For operations with large operations and IO operations, we need new threads to handle these heavy work, so as not to block the UI thread.
Example: below we take the example of obtaining the CSDN logo, demonstrating how to implement the UI thread update interface by using Thread+handler to send message notifications on non-UI threads.
Thradhandleractivity.java:
Public classThreadhandleractivityextendsActivity {/**Called when the activity is first created.*/ Private Static Final intmsg_success = 0;//get a picture of a successful identity Private Static Final intMsg_failure = 1;//gets the identity of the picture failure PrivateImageView Mimageview; PrivateButton Mbutton; PrivateThread Mthread; PrivateHandler Mhandler =NewHandler () { Public voidHandlemessage (Message msg) {//This method runs on the UI thread Switch(msg.what) { CaseMSG_SUCCESS:mImageView.setImageBitmap ((Bitmap) msg.obj);//ImageView Display the logo obtained from the networkToast.maketext (Getapplication (), Getapplication (). getString (r.string.get_pic_success), Toast.length_lo NG). Show (); Break; CaseMSG_FAILURE:Toast.makeText (Getapplication (), Getapplication (). getString (R.string.get_pic_failure), to Ast. Length_long). Show (); Break; } } }; @Override Public voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate); Setcontentview (R.layout.main); Mimageview= (ImageView) Findviewbyid (R.id.imageview);//Display the ImageView of a pictureMbutton =(Button) Findviewbyid (R.id.button); Mbutton.setonclicklistener (NewOnclicklistener () {@Override Public voidOnClick (View v) {if(Mthread = =NULL) {Mthread=NewThread (runnable); Mthread.start ();//Thread Start } Else{Toast.maketext (Getapplication (), Getapplication (). getString (r.string.thread_started), Toast.leng Th_long). Show (); } } }); } Runnable Runnable=NewRunnable () {@Override Public voidRun () {//run () runs in a new threadHttpClient HC =Newdefaulthttpclient (); HttpGet HG=NewHttpGet ("Http://csdnimg.cn/www/images/csdnindex_logo.gif");//get CSDN's logo FinalBitmap BM; Try{HttpResponse hr=Hc.execute (Hg); BM=Bitmapfactory.decodestream (Hr.getentity (). getcontent ()); } Catch(Exception e) {mhandler.obtainmessage (msg_failure). Sendtotarget ();//failed to get picture return; } mhandler.obtainmessage (MSG_SUCCESS,BM). Sendtotarget ();//get picture successful, send msg_success identity and bitmap object to UI thread//Mimageview.setimagebitmap (BM);//Error! UI elements cannot be manipulated on non-UI threads//Mimageview.post (New Runnable () {//another more concise way to send messages to the UI thread. // //@Override//Public void Run () {//the Run () method executes on the UI thread//Mimageview.setimagebitmap (BM);// }// }); } }; }
Main.xml layout file:
<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android " android:orientation=" vertical "android:layout_width=" fill_parent " android:layout_ Height= "fill_parent" > <button android:id= "@+id/button" android:text= "@string/button_name" Android: Layout_width= "Wrap_content" android:layout_height= "wrap_content" ></Button> <imageview Android:id = "@+id/imageview" android:layout_height= "wrap_content" android:layout_width= "Wrap_content"/> </LinearLayout>
Strings.xml:
<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android " android:orientation=" vertical "android:layout_width=" fill_parent " android:layout_ Height= "fill_parent" > <button android:id= "@+id/button" android:text= "@string/button_name" Android: Layout_width= "Wrap_content" android:layout_height= "wrap_content" ></Button> <imageview Android:id = "@+id/imageview" android:layout_height= "wrap_content" android:layout_width= "Wrap_content"/> </LinearLayout>
Manifest.xml:
<?xml version= "1.0" encoding= "Utf-8"? ><manifest xmlns:android= "Http://schemas.android.com/apk/res/android" Package= "Com.zhuozhuo"Android:versioncode= "1"Android:versionname= "1.0" > <uses-sdk android:minsdkversion= "9"/> <uses-permission android:name= "Android.permission.INTERN ET "></uses-permission><!--Don't forget to set network access rights--<application android:icon=" @drawable/icon "Android: Label= "@string/app_name" > <activity android:name= ". Threadhandleractivity "Android:label= "@string/app_name" > <intent-filter> <action android:name= "Android.intent.action.MAI N "/> <category android:name=" Android.intent.category.LAUNCHER "/> </INTENT-FILTER&G T </activity> </application></manifest>
Operation Result:
To not block the UI thread, we used Mthread to get the CSDN logo from the web
and stores the pixel information of this logo with the bitmap object.
At this point, if you call in the run () method of this thread
Mimageview.setimagebitmap (BM)
will appear: Calledfromwrongthreadexception:only the original thread that created a view hierarchy can touch it views. The reason is that the run () method is executed in the newly opened thread, and we mentioned above that we cannot manipulate UI elements directly in a non-UI thread.
A non-UI thread sends a message to the UI thread in two steps
One, Message Queuing for sending messages to the UI thread
By using the handler
Message obtainmessage (int what,object Object)
Constructs a message object that stores the successful acquisition of the image's identity what and bitmap object, and then puts the message into the queue of messages through the Message.sendtotarget () method.
II. handling messages sent to the UI thread
In the UI thread, we covered the handler
Public void
This method is to handle the message distributed to the UI thread, to determine the value of msg.what can know whether Mthread successfully obtained the picture, if the picture is successfully obtained, then you can get to this object through Msg.obj.
Finally, we pass
Mimageview.setimagebitmap ((Bitmap) msg.obj);
Set the ImageView Bitmap object to complete the UI update.
Add:
In fact, we can also call
View's post method to update the UI
Mimageview.post (new Runnable () {/// Another more concise way to send messages to the UI thread. the @Override publicvoid run () {///Run () method executes on the UI thread Mimageview.setimagebitmap (BM); } });
This method sends the Runnable object to the message queue, which executes the Runnable object when the UI thread receives the message.
From the example we can see that handler both send messages and processing messages, will mistakenly think that handler implementation of the message loop and message distribution, in fact, Android in order to make our code look more concise, Interacting with the UI thread only requires the use of the handler object created on the UI thread. To learn more about the specific implementation of the message loop mechanism, please focus on Android asynchronous processing three: Handler+looper+messagequeue in-depth
Engineering Package Download: Http://www.androidtwitters.com/blog/threadhandler.rar
This blog address: http://blog.csdn.net/mylzc/article/details/6736988 reprint please indicate the source
Android Asynchronous Processing (i)