AsyncTask is an Helper class that allows you to perform background operations and updating the UI when the task completes. After the execution of the Background task, the results are published on the UI thread. It is ideal for running short operations that spans for few seconds. It serves better when compared to Threads and handlers since it enables proper and easy use of the UI thread.
- Buy: Hello, Android!!
The AsyncTask class encapsulates the creation of Threads and Handlers. When an AsyncTask is created, it goes through 4 steps,
- onPreExecute()
- doInBackground(Params…)
- onProgressUpdates(Progress…)
- onPostExecute(Result)
The method doInBackgroung() executes automatically on a worker thread. The rest of the methods onPreExecute(), onPostExecute(), and onProgressUpdate() are all invoked on the UI thread. The value returned from the doInBackground() is sent to the onPostExecute() method. onProgressUpdate() method is executed by calling publishProgress() in doInBackground(). Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params…), onProgressUpdate(Progress…) manually. Overriding onPreExecute(), onPostExecute(Result), onProgressUpdate(Progress…) is optional.
AsyncTask is defined by three generic types Params, Progress, Result,
class AsyncDemo extends AsyncTask<Params, Progress, Result> { ... }
- Params
It is the type of the parameters passed in to the doInBackground. - Progress
It is the type of the progress units published during the backgroung computation. These are passed in to the onProgressUpdate. - Result
It is the return type of doInBackground and argument type passed in to onPostExecute.
An AsyncTask must be subclassed to be used as below,
private class AsyncDemo extends AsyncTask<String, String, String>{ @Override protected void onPreExecute() { // keeps the user informed about the long running tasks example by showing progressbar etc. super.onPreExecute(); } @Override protected String doInBackground(String... params) { // The code of long running tasks goes here return null; } @Override protected void onProgressUpdate(String... values) { //when the long running tasks is in progress, the code to update the progress example updating the progress bar super.onProgressUpdate(values); } @Override protected void onPostExecute(String result) { //once the background work is done with execution, update the UI... super.onPostExecute(result); } }
The above snippet shows how you can create An AsyncTask for your operations. Once created, the Task is executed using the below line,
new AsyncDemo().execute();
While calling execute() method, pass the parameters which your AsyncTask is using.
Working of an AsyncTask
When an AsyncTask is executed by calling execute() method, it goes through 4 steps as stated above,
- It first goes to onPreExecute() method, which is used to setup the Task. This can be used to keep the user informed about the Task that executes in background by showing a progressdialog.
- Then the control goes to doInBackground() method where the expensive work takes place. This is invoked immediately after onPreExecute() finishes executing. The parameters of the AsyncTask are passed(if any) to this method. The results are returned and are passed to the onPostExecute() method which processess the result and updates the UI accordingly if necessary.
- publishProgress(Progress…) can be called inside doInBackground() method which in turn calls the onProgressUpdate(Progress…) to publish one or more units of progress.
- After the backgroud task finishes its computation, onPostExecute(Result) is invoked. The Result of the background computation is passed as parameter to this step from the doInBackground(Params…) step. onPostExecute(Result) updates the UI(Example: Cancelling the ProgressDialog etc);
Let us now look at a simple example on how to execute long running tasks using AsyncTask
Working of the below AsyncTask example
In this example we would be displaying numbers in regular intervals of time forming a counterdown timer. The number of numerics to count is obtained from the user using an EditText. When the user clicks on a button called “Count”, the textview in the layout file starts showing numbers from 1 to any numeric specied by the user.(say 1 to 10 if your input is 10). When the numeric say 10 is displayed, the countdown stops and displays a message “Your countDown timer has stopped”.
Follow the below steps to create the example,
Step 1: Set up an android working environment
If you are not familiar with setting up the android environment, please refer to one of our earliar post, Environment. I would be using Android2.2 for this example.
Step 2 : Create an android project
Create a project named “AsyncTaskDemo” with the activity “ActivityAsyncTask”. If you are not familiar with creation of android project, please refer the post Create an Android project.
step 3: Create a layout
When you create your project, the layout main.xml gets created automatically. Here in this example we are going to use this main.xml layout file. Open your main.xml and paste the below code.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/RelativeLayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>"> <EditText android:id="@+id/EditText01" android:layout_height="wrap_content" android:layout_width="90dip"></EditText> <Button android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/EditText01" android:text="Count"></Button> <TextView android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textStyle="bold" android:textSize="18sp"></TextView> </RelativeLayout>
Step 4: Create the required Activities
Here in this example I would be using the launcher activity ActivityAsyncTask.java. Open this activity and paste the below code,
package my.app; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class ActivityAsyncTask extends Activity { EditText input_time; TextView count_textview; Button start_count; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); start_count=(Button)findViewById(R.id.Button01); count_textview=(TextView)findViewById(R.id.TextView01); input_time=(EditText)findViewById(R.id.EditText01); start_count.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub //taking the input from the edittext String input_number=input_time.getText().toString(); Integer input_time_int=Integer.parseInt(input_number); //Starting CountDownStarterTask task by passing the parameter new CountDownStarterTask().execute(input_time_int); } }); } private class CountDownStarterTask extends AsyncTask<Integer, Integer, Void>{ @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); } @Override protected Void doInBackground(Integer... params) { // TODO Auto-generated method stub for(int i=1;i<=params[0].intValue();i++){ try { //calls onProgressUpdate to publish the progress publishProgress(i); Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } @Override protected void onProgressUpdate(Integer... values) { // TODO Auto-generated method stub super.onProgressUpdate(values); Integer time_to_set=values[0].intValue(); count_textview.setText(time_to_set.toString()); } @Override protected void onPostExecute(Void result) { // TODO Auto-generated method stub super.onPostExecute(result); count_textview.setText("Your countDown timer has stopped"); } } }
As you can observe in the above code, we have an Edittext which collects the user input. You have to enter a numeric input and click on “Count” button. Which starts counting number from 1 to max number that you have given as input.
Step 5: Declaring the Activities in Android Manifest file
Your launcher activity is declared automatically. If you want to know more about android Manifest xml file, please refer to the post AndroidManifest.xml.
Your manifest file has the below code,
<manifest xmlns:android="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>" package="my.app" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".ActivityAsyncTask" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="8" /> </manifest>
Step 6: Run your App
Select your project-> Right click-> Run As-> Android Application
Activity ActivityAsyncTask fires up as below.
Enter a number of your choice(say 10) in the EditText and click on the button “Count”. Now the countDown starts as below.
When the count reaches 10 it stops and the below message appears on screen.
This is how you can make your long running tasks to run using AsyncTask without blocking the main UI thread. AsyncTask starting with DONUT was offering multitasking by using pool of threads whereas starting with HONEYCOMB, it uses single threading model. If you truly want parallel execution, you can always use executeOnExecutor(java.util.concurrent.Executor, Object[]) instead of execute(). Hope this tutorial helped you. Please post your queries, doubts if any in the comments section.