How to Use AsyncTask in Android

Source: Internet
Author: User

How to Use AsyncTask in Android

In Android, we can use Thread + Handler to implement multi-Thread communication. A typical scenario is to perform time-consuming operations in the new Thread. After the task is completed, Handler sends a Message to the main Thread, in this way, the Handler of the main thread can update the UI after receiving the Message. In the above scenario, we need to write the code logic in the Thread and Handler respectively. To make the code more unified, we can use the AsyncTask class.

AsyncTask is an Assistant class provided by Android. It encapsulates Thread and Handler for our convenience. Android provides the AsyncTask class to facilitate operations in the background thread, and then send the results to the main thread to perform operations such as UI update in the main thread. When using AsyncTask, we don't need to pay attention to Thread and Handler. AsyncTask is managed internally, so we only need to pay attention to our business logic.

AsyncTask has four important callback Methods: onPreExecute, doInBackground, onProgressUpdate, and onPostExecute. These four methods will be automatically called at different times of AsyncTask. We only need to implement the internal logic of these methods. The parameters and returned values of these four methods are both generic and the types of generics are different. Therefore, three generic parameters are met in AsyncTask: Params, progress and Result, as shown in:

Params indicates the type of parameters used for AsyncTask to execute tasks. SS indicates the data type of results that can be released in stages during background thread processing. Result indicates the data type returned after all tasks are completed.

We pass in parameters and execute the task by calling the execute () method of AsyncTask. Then AsyncTask calls the following four methods in sequence:

OnPreExecute
The signature of this method is as follows:

This method hasMainThreadAnnotation, indicating that the method is running in the main thread. After AsyncTask executes the execute () method, it will execute the onPreExecute () method on the UI thread. This method runs before the task is actually executed, we can usually display a progress bar in this method to inform the user that the background task is about to begin.

DoInBackground
The signature of this method is as follows:

This method hasWorkerThreadAnnotation, indicating that the method runs in a separate working thread, rather than in the main thread. DoInBackground will be executed immediately after the onPreExecute () method is executed. This method is used to execute time-consuming tasks in the work thread, we can compile the logic code we need to run in the background thread in this method. Because it is running in the working thread, this method will not block the UI thread. This method receives Params generic parameters. The parameter params is an indefinite array of the Params type. The returned value of this method is Result generic. Because doInBackgroud is an abstract method, we must override this method when using AsyncTask. The tasks executed in doInBackground may be divided into multiple steps. After each step is completed, we can call the publishProgress (Progress…) of AsyncTask ...) Publish the staged processing results. The staged processing results are of the Progress generic type. After the publishProgress method is called, the processing result is passed to the UI thread and the onProgressUpdate method is called back in the UI thread. The following describes in detail. According to our specific needs, we can do not call the publishProgress method in doInBackground. Of course, we can also call the publishProgress method multiple times in this method. The Return Value of the doInBackgroud method indicates the result after the background thread completes the task.

OnProgressUpdate
As we know above, when we call publishProgress (Progress…) in doInBackground ...) The onProgressUpdate method is called back in the UI thread. The method signature is as follows:

This method also hasMainThreadAnnotation, indicating that the method is called on the main thread, and the input parameter is an indefinite array defined by the Progress generic type. If the publishProgress method is called multiple times in doInBackground, the main thread will call back the onProgressUpdate method multiple times.

OnPostExecute
The signature of this method is as follows:

This method also hasMainThreadAnnotation, indicating that the method is called in the main thread. After the doInBackgroud method is executed, the task is completed. The return value of the doInBackgroud method is passed into the onPostExecute method as a parameter in the main thread, in this way, you can update the UI Based on the task execution results in the main thread.

The following example shows how to use AsyncTask to download multiple files.

The layout file is as follows:


      
      
   

There is a "Start download" button on the interface. Click this button to download multiple files through AsyncTask. The corresponding Java code is as follows:

Package com. ispring. asynctask; import android. app. activity; import android. OS. asyncTask; import android. OS. build; import android. OS. bundle; import android. util. log; import android. view. view; import android. widget. button; import android. widget. textView; import java. io. byteArrayOutputStream; import java. io. IOException; import java. io. inputStream; import java.net. httpURLConnection; import java.net. malformedURLException; import java.net. URL; public class MainActivity extends Activity implements Button. onClickListener {TextView textView = null; Button btnDownload = null; @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); textView = (TextView) findViewById (R. id. textView); btnDownload = (Button) findViewById (R. id. btnDownload); Log. I ("iSpring", "MainActivity-> onCreate, Thread name:" + Thread. currentThread (). getName () ;}@ Override public void onClick (View v) {// address of the file to be downloaded String [] urls = {"http://blog.csdn.net/iispring/article/details/47115879", "http://blog.csdn.net/iispring/article/details/47180325 ", "http://blog.csdn.net/iispring/article/details/47300819", "http://blog.csdn.net/iispring/article/details/47320407", "http://blog.csdn.net/iispring/article/details/47622705"}; DownloadTask downloadTask = new DownloadTask (); downloadTask.exe cute (urls);} // public abstract class AsyncTask
  
   
// In this example, the Params generic type is String type, the Progress generic type is Object type, and the Result generic type is Long type private class DownloadTask extends AsyncTask
   
    
{@ Override protected void onPreExecute () {Log. I ("iSpring", "DownloadTask-> onPreExecute, Thread name:" + Thread. currentThread (). getName (); super. onPreExecute (); btnDownload. setEnabled (false); textView. setText ("START download... ") ;}@ Override protected Long doInBackground (String... params) {Log. I ("iSpring", "DownloadTask-> doInBackground, Thread name:" + Thread. currentThread (). getName (); // totalByte Indicates the total number of bytes of all downloaded files long totalByte = 0; // params is a String array for (String url: params) {// traverses the Url array, download the corresponding Object [] result = downloadSingleFile (url); int byteCount = (int) result [0]; totalByte + = byteCount; // After downloading an Object, we will release the phased processing result publishProgress (result); // if AsyncTask is called the cancel () method, the task is canceled and the for loop if (isCancelled () exists ()) {break ;}/// return the total number of downloaded bytes as the result. return totalByte;} // returns an array of objects after the Object is downloaded: the number of bytes of the downloaded file and the blog Private Object [] downloadSingleFile (String str) {Object [] result = new Object [2]; int byteCount = 0; String blogName = ""; HttpURLConnection conn = null; try {URL url = new URL (str); conn = (HttpURLConnection) url. openConnection (); InputStream is = conn. getInputStream (); ByteArrayOutputStream baos = new ByteArrayOutputStream (); byte [] buf = new byte [1024]; int length =-1; while (length = is. r Ead (buf ))! =-1) {baos. write (buf, 0, length); byteCount + = length;} String respone = new String (baos. toByteArray (), "UTF-8"); int startIndex = respone. indexOf ("
    "); If (endIndex> startIndex) {// parse the title blogName = respone in the blog. substring (startIndex, endIndex) ;}} catch (MalformedURLException e) {e. printStackTrace ();} catch (IOException e) {e. printStackTrace ();} finally {if (conn! = Null) {conn. disconnect () ;}} result [0] = byteCount; result [1] = blogName; return result ;}@ Override protected void onProgressUpdate (Object... values) {Log. I ("iSpring", "DownloadTask-> onProgressUpdate, Thread name:" + Thread. currentThread (). getName (); super. onProgressUpdate (values); int byteCount = (int) values [0]; String blogName = (String) values [1]; String text = textView. getText (). toString (); text + = "\ n blog" + blogName + "" downloaded, total "+ byteCount +" Byte "; textView. setText (text) ;}@ Override protected void onPostExecute (Long aLong) {Log. I ("iSpring", "DownloadTask-> onPostExecute, Thread name:" + Thread. currentThread (). getName (); super. onPostExecute (aLong); String text = textView. getText (). toString (); text + = "\ n all downloaded, total downloaded" + aLong + "bytes"; textView. setText (text); btnDownload. setEnabled (true) ;}@ Override protected void onCancelled () {Log. I ("iSpring", "DownloadTask-> onCancelled, Thread name:" + Thread. currentThread (). getName (); super. onCancelled (); textView. setText ("cancel download"); btnDownload. setEnabled (true );}}}
   
  

After you click the Download button, the page is shown as follows:

The console output is as follows:

The above code is described below.

In MainActivity, we define the internal class DownloadTask. DownloadTask inherits from AsyncTask. In this example, the Params generic type is String type, and the Progress generic type is Object type, the Result generic type is the Long type.

We define a Url string array that is passed to the execute method of AsyncTask for asynchronous task execution.

IndownloadTask.execute(urls)Then, AsyncTask automatically calls back the onPreExecute method. In this method, we set textView to "Start download ..." To notify the user of the upcoming download operation. The console output shows that this method is executed in the main thread.

After the onPreExecute method is executed, AsyncTask calls back the doInBackground method. The input parameter in this method is an indefinite array of the String type, and the String here corresponds to the Params generic type, in this method, we traverse the Url array and download the corresponding files in sequence. When we download an object, it is equivalent to completing some tasks in stages, we call publishProgress to publish the phased processing results. In this example, we define the stage processing result as the Object type, that is, the Progress generic type. Through the console output, we can see that the doInBackground method runs in the new working thread "AsyncTask #1", and the working threads of AsyncTask use "AsyncTask #" and then add a number as the name. After all files are downloaded, we can use totalSize to return the number of bytes downloaded. The returned value type is Long, which corresponds to the Result generic type in AsyncTask.

In the doInBackground method, every time a file is downloaded, we call the publishProgress method to publish the stage result. Then, AsyncTask calls back the onProgressUpdate method. In this example, the onProgressUpdate parameter is of the Object type, corresponds to the SS generic type in AsyncTask. Through the console output, we can find that this method is called in the main thread. In this method, we will update the UI through textView to tell the user which file has been downloaded, in this way, the user experience is relatively friendly.

After the entire doInBackground method is executed, AsyncTask calls back the onPostExecute method. In this method, we use textView to update the UI to notify the user that all download tasks have been completed.

After an asynchronous task is executed using the execute method, you can use the cancel Method of AsyncTask to cancel the task. After the task is canceled, AsyncTask calls back the onCancelled method, so that the onPostExecute method is no longer called.

When using Android, pay attention to the following points:

The instance of AsyncTask must be created in the main thread.

The execute method of AsyncTask must be called in the main thread.

OnPreExecute (), onPostExecute (Result), doInBackground (Params ...) And onProgressUpdate (Progress ...) All the four methods are callback methods, which are automatically called by Android and should not be called by ourselves.

For an AsyncTack instance, only the execute method can be executed once. An exception is thrown when the first execute method is executed for this instance.

The above example shows how to use AsyncTask. As mentioned above, an AsyncTask instance can only execute the execute method once. What if we want to execute multiple tasks in parallel? We can consider instantiating multiple AsyncTask instances and then calling the execute method of each instance. To explore the effect, we can change the Code as follows:

Public void onClick (View v) {// file address to download String [] urls = {"http://blog.csdn.net/iispring/article/details/47115879", "http://blog.csdn.net/iispring/article/details/47180325", "http://blog.csdn.net/iispring/article/details/47300819", "http://blog.csdn.net/iispring/article/details/47320407 ", "http://blog.csdn.net/iispring/article/details/47622705"}; DownloadTask downloadTask1 = new DownloadTask (); downloadTask1.execute (urls); DownloadTask downloadTask2 = new DownloadTask (); downloadTask2.execute (urls );}

After clicking the button, we instantiate two downloadtasks and execute their execute methods respectively. The following figure shows the running interface:

The console output is as follows:

After observing the output result of the console, we can find that for downloadTask1, The doInBackground method runs in the thread "AsyncTask #1"; for downloadTask2, the doInBackground method runs in the thread "AsyncTask #2". At this time, we may think it is very good. The two AsyncTask instances run in different threads and implement parallel processing. Is it true that it runs in parallel?

After observing the console output, we can find that the doInBackground method of downloadTask1 is executed, five files are downloaded, and onProgressUpdate is triggered five times. After that, the downloadTask2 doInBackground method is executed. After downloadTask1 downloads five articles in sequence, downloadTask2 downloads five articles in sequence. To sum up, we can know that by default, if AsyncTask is created to create multiple instances and execute each execute method of the instance at the same time, the execute methods of these instances are not executed in parallel and are executed in serial mode. That is, after the doInBackground of the First Instance completes the task, the doInBackgroud method of the second instance starts to be executed, then execute the doInBackground method of the third instance... You may ask, no, the downloadTask1 is running in the "AsyncTask #1" thread, and downloadTask2 is running in the "AsyncTask #2" thread, there are two threads! In fact, AsyncTask opened a working thread named "AsyncTask #1" for downloadTask1, which may be destroyed after the task is completed, then AsyncTask opened a working thread named "AsyncTask #2" for downloadTask2.

AsyncTask uses a single background thread to execute tasks of multiple AsyncTask instances in the earliest version. Starting from Android 1.6 (DONUT), AsyncTask uses the thread pool to execute asynchronous tasks in parallel, however, starting from Android 3.0 (HONEYCOMB), to avoid common errors caused by parallel execution, AsyncTask uses a single thread as the working thread to process multiple tasks by default.

The executeOnExecutor method has been added to AsyncTask since Android 3.0. This method allows AsyncTask to process tasks in parallel. The method signature of this method is as follows:

public final AsyncTask
  
    executeOnExecutor (Executor exec, Params... params)
  

The first parameter indicates that exec is an Executor object. To allow AsyncTask to process tasks in parallelAsyncTask.THREAD_POOL_EXECUTORYou can,AsyncTask.THREAD_POOL_EXECUTORIt is a built-in thread pool object in AsyncTask. Of course, we can also input our own instantiated thread pool object. The second parameter params indicates the parameters of the task to be executed.

The sample code for parallel task execution using the executeOnExecutor method is as follows:

public void onClick(View v) {        if(Build.VERSION.SDK_INT >= 11){            String[] urls = {                    "http://blog.csdn.net/iispring/article/details/47115879",                    "http://blog.csdn.net/iispring/article/details/47180325",                    "http://blog.csdn.net/iispring/article/details/47300819",                    "http://blog.csdn.net/iispring/article/details/47320407",                    "http://blog.csdn.net/iispring/article/details/47622705"            };            DownloadTask downloadTask1 = new DownloadTask();            downloadTask1.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, urls);            DownloadTask downloadTask2 = new DownloadTask();            downloadTask2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, urls);        }    }

We instantiate two DownloadTask instances, then execute the executeOnExecutor method of the two instances, andAsyncTask.THREAD_POOL_EXECUTORAs the Executor, both receive the same Url array as the task execution parameter.

After clicking the Download button, the running interface is shown as follows:

The console output is as follows:

The output result of the console shows that after downloadTask1 executes the doInBackground method, downloadTask2 immediately executes the doInBackground method. In addition, you can see that after an article is downloaded from a DownloadTask instance on the UI interface after the program is run, another DownloadTask instance immediately downloads an article. The two DownloadTask instances download files in different order, we can see that the two AsyncTask instances are executed in parallel.

If you want to know how AsyncTask works, refer to another blog titled working principles of AsyncTask in Android source code parsing.

I hope this article will help you use AsyncTask!

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.