Updating the contents of the UI on the Android sub-thread will result in an indeterminate exception.
Because Android has a pattern, a single-thread model: The Android UI Toolbox (Toolkit) is not a threading-safe, and it is always placed on the main thread.
Public void OnClick (View v) { new Thread (new Runnable () { publicvoid Run () { = loadimagefromnetwork (); Mimageview.setimagebitmap (b); } }). Start ();}
First, the code from above looks perfect because it does not block the UI thread, and unfortunately it violates the single threading model: the Android UI Toolbox (Toolkit) is not a thread-safe, and it is always placed on the main thread.
This imageview is manipulated by a worker thread, which leads to a very magical problem. Tracking and repairing such a bug is difficult and time-consuming. Android provides several ways to access the main thread from other threads:
- Activity.runonuithread (Runnable)
- View.post (Runnable)
- View.postdelayed (Runnable, long)
- Handler
Any of these methods can fix our code:
Public void OnClick (View v) { new Thread (new Runnable () { publicvoid Run () { final Bitmap b = loadimagefromnetwork (); Mimageview.post (new Runnable () { publicvoid run () { Mimageview.setimagebitmap (b);}) ;} ). Start ();}
Of course we have an easier way to use Asynctask
Unfortunately, these classes and methods cause our code to become complex and poorly readable. When you implement complex operations to update the interface frequently, it's much worse to use this approach. To solve this problem, Android1.5 provides a public class called Asynctask, which simplifies communication between the task thread and the main thread. can also be used in Android1.0 and 1.1 Asynctask except its name is Usertask. The purpose of Asynctask is to help you manage threads. Our previous example can easily be rewritten as follows:
public void OnClick (View v) { new Downloadimagetask ( ). Execute ("http://example.com/image.png" private class Downloadimagetask extends asynctask<string, Integer, Bitmap> { protected Bitmap Doinbackground ( String ... urls) { return loadimagefromnetwork (urls[0]); protected void OnPostExecute (Bitmap result) {Mimageview.setimagebitmap (result); } }
Asynctask can be used by its subclasses. Remember that a asynctask instance must be created on the main thread and can only be executed once. Fully understand and use this class, you can read the Asynctask documentation. Here's a quick talk about how Asynctask works.:1> can specify its type by generic type: parameter, progress value, task result value. The 2>doinbackground () method automatically only wants to be able in the worker thread. 3>onpreexecute (), OnPostExecute (), Onprogressupdate () methods are all executed in the UI thread. The value returned by the 4>doinbackground () method is passed as a parameter to the OnPostExecute () method. 5> you can call the Publishprogress () method at any time in the Doinbackground () method to execute the Onprogressupdate () method in the UI thread. Here is an overloaded method to compare many classes:
1 PackageVic.wong.main;2 ImportAndroid.os.AsyncTask;3 ImportAndroid.widget.ProgressBar;4 ImportAndroid.widget.TextView;5 6 /**7 * After generating the object of the class and calling the Execute method8 * The first thing to do is the Onproexecute method9 * Second implementation of the Doinbackgroup methodTen * One */ A Public classProgressbarasynctaskextendsAsynctask<integer, Integer, string> { - PrivateTextView TextView; - PrivateProgressBar ProgressBar; the PublicProgressbarasynctask (TextView TextView, ProgressBar ProgressBar) { - Super(); - This. TextView =TextView; - This. ProgressBar =ProgressBar; + } - /** + * The integer parameter here corresponds to the first parameter in Asynctask A * The string return value here corresponds to the third parameter of Asynctask at * This method does not run in the UI thread, primarily for asynchronous operations, where the space in the UI cannot be set and modified - * However, you can invoke the Publishprogress method to trigger Onprogressupdate to manipulate the UI - */ - @Override - protectedString doinbackground (Integer ... params) { -Netoperator Netoperator =Newnetoperator (); in inti = 0; - for(i = ten; I <=; i+=10) { to netoperator.operator (); + publishprogress (i); - } the returni + params[0].intvalue () + ""; * } $ Panax Notoginseng /** - * The string parameter here corresponds to the third parameter in Asynctask ( that is, the return value of the receiving Doinbackground) the * Run at the end of the Doinbackground method execution and run in the UI thread to set the UI space + */ A @Override the protected voidOnPostExecute (String result) { +Textview.settext ("End of asynchronous operation execution" +result); - } $ //This method runs in the UI thread and runs within the UI thread to set the UI space $ @Override - protected voidOnPreExecute () { -Textview.settext ("Start executing asynchronous Threads"); the } - /**Wuyi * The Intege parameter here corresponds to the second parameter in the Asynctask the * In the Doinbackground method, each call to the Publishprogress method will trigger Onprogressupdate execution - * Onprogressupdate is executed in the UI thread, all of which can manipulate the UI space Wu */ - @Override About protected voidonprogressupdate (Integer ... values) { $ intVlaue = Values[0]; - progressbar.setprogress (Vlaue); - } -}
Android UI thread safety issues