How to use AsyncTask in Android?

Android implements single thread model and whenever an android application is launched, a thread is created. Assuming we are doing network operation on a button click in our application. On button click a request would be made to the server and response will be awaited. Due to single thread model of android, till the time response is awaited our screen is non-responsive. So we should avoid performing long running operations on the UI thread. This includes file and network access.

To overcome this we can create new thread and implement run method to perform this network call, so UI remains responsive.

But since Android follows single thread model and Android UI toolkit is not thread safe, so if there is a need to make some change to the UI based on the result of the operation performed, then this approach may lead some issues.

So the Android framework has given a very good pattern which is enveloped into AsyncTask.


Note: AsyncTask should ideally be used for operations that take few seconds. Some tasks keep the thread running for long time so in that case it is recommended to use java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.

AsyncTask :


 AsyncTask is an abstract class provided by Android which helps us to use the UI thread properly. The AsyncTask class encapsulates the creation of a background process and the synchronization with the main thread. It also supports reporting progress of the running tasks.

The most common methods you will need to implement are these:

1. onPreExecute() – called on the UI thread before the thread starts running. This method is usually used to setup the task, for example by displaying a progress bar.

2. doInBackground(Params…) – this is the method that runs on the background thread. In this method you should put all the code you want the application to perform in background like Network access, file or database access.

3. onProgressUpdate() –It is called when you invoke publishProgress() in the doInBackground().

4. onPostExecute(Result) – called on the UI thread after the background thread finishes. It takes as parameter the result received from doInBackground().

AsyncTask’s generic types


The three types used by an asynchronous task are the following:

  1. Params, the type of the parameters sent to the task upon execution.

  2. Progress, the type of the progress units published during the background computation.

  3. Result, the type of the result of the background computation.

Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:

private class MyTask extends AsyncTask<Void, Void, Void> { ... }

The 4 steps (Methods of AsyncTask)


When an asynchronous task is executed, the task goes through 4 steps:

  1. onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.

  2. doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.

  3. onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.

  4. onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.

Cancelling a task


A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)

Using the AsyncTask class


To use AsyncTask you must subclass it. AsyncTask uses generics and varargs. The parameters are the following AsyncTask <TypeOfVarArgParams , ProgressValue , ResultValue> .

An AsyncTask is started via the execute() method.

The execute() method calls the doInBackground() and the onPostExecute() method.

TypeOfVarArgParams is passed into the doInBackground() method as input, ProgressValue is used for progress information and ResultValue must be returned from doInBackground() method and is passed to onPostExecute() as a parameter.

The doInBackground() method contains the coding instruction which should be performed in a background thread. This method runs automatically in a separate Thread.

The onPostExecute() method synchronizes itself again with the user interface thread and allows it to be updated. This method is called by the framework once the doInBackground() method finishes.

Example

In this sample application I just made the process to sleep for some period of time instead of doing network operation.( Just to explain the concept of AsyncTask. This is not a realtime application)

When the user clicks on the Start AsyncTask button, we make the process to sleep for give period of time. At the same time we keep the UI thread responsive by showing the status to the user.

Layout is like this:

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">

<TextView
android:id="@+id/output"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"/>

<Button
android:id="@+id/startTask"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/strBtnStart"
android:layout_below="@id/output"
android:onClick="startTask"/>

</RelativeLayout>

Main_Activity.java file is as follow:

 

package com.example.async1;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

//Method called on clicking button
public void startTask(View view) {
myAsyncTask mTask = new myAsyncTask();
mTask.execute("abc","10","Hello world");
}

private class myAsyncTask extends AsyncTask<String, Integer, String> {
String mTAG = "myAsyncTask";
@Override
protected void onPreExecute() {
TextView output = (TextView)findViewById(R.id.output);
output.setText("Hello from onPreExecute");
displayProgressBar("Loading....");
}

@Override
protected String doInBackground(String...arg) {
Log.d(mTAG, "Just started doing stuff in asynctask");
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(mTAG, "I got "+arg.length+" arguments and they are: ");
String result = null;
for (int i = 0 ; i < arg.length ; i++ ) {
result = arg[i]+",";
Log.d(mTAG, (i+1)+" => "+arg[i]);
}

/*runOnUiThread(new Thread() {
public void run() {
TextView output = (TextView) findViewById(R.id.output);
output.setText("I am done");
}
});*/

try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}

return result;
}

@Override
protected void onPostExecute(String result) {
Log.d(mTAG, "Inside onPostExecute");
TextView output = (TextView) findViewById(R.id.output);
output.setText("Result of the computation is: "+result);
}

}

}

As we know that doInBackground() method can’t update UI Thread because it runs on background. Still if we want to update UI thread inside this method, we use runOnUiThread() method that takes a new Thread as an argument, in which we can update UI Thread.

Uncomment runOnUiThread() method written inside code to see its effect.

Task: Use AsyncTask onProgressUpdate() Method.


package com.example.async1;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {
    private TextView output;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        output = (TextView)findViewById(R.id.output);
        
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
    //This function is called when button is clicked.
    public void startTask(View view) {
        myAsyncTask mTask = new myAsyncTask();
        mTask.execute("abc","10","Hello world");
    }
    
    private class myAsyncTask extends AsyncTask<String, Integer, Void> {
        String mTAG = "myAsyncTask";
        
        @Override
        protected void onPreExecute() {
            Log.d(mTAG, "Hello from onPreExecute");
            output.setText("Hello from onPreExecute");
        }
        
        @Override
        protected Void doInBackground(String...arg) {
            
            //Added sleep so that you can see Hello from onPreExecute and after that Inside doInBackground clearly.
            try{
                Thread.sleep(5000);
            }
            catch(InterruptedException e)
            {
                
                e.printStackTrace();
            }
            
            Log.d(mTAG, "Just started doing stuff in background");
            //New thread is created because this function can't update UI Thread.
            runOnUiThread(new Thread() {
                public void run() {
                    TextView output = (TextView) findViewById(R.id.output);
                    output.setText("Inside doInBackground");
                }
            });
            
            //Showing arguments passed to it by execute() method.
            Log.d(mTAG, "I got "+arg.length+" arguments and they are: ");
            for (int i = 0 ; i < arg.length ; i++ ) {
                Log.d(mTAG, (i+1)+" => "+arg[i]);
            }
            
            //Continuous BackGround Work
            for(int i=0;i<10;i++){
            try {
                Thread.sleep(5000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            publishProgress(i+1); // It calls onProgressUpdate Method.
            }
            
            return null;
        }
        
        //@Override
        protected void onProgressUpdate(Integer ... a){
                Log.d(mTAG,"Progress is "+a[0]+" % done.");
                output.setText(a[0]+"% done");
            
        }
        
        @Override
        protected void onPostExecute(Void a) {
            Log.d(mTAG, "Inside onPostExecute");
            output.setText("Work Done!");
        }
    }
    
}


References:

http://developer.android.com/reference/android/os/AsyncTask.html

http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html

http://www.compiletimeerror.com/2013/01/why-and-how-to-use-asynctask.html

 

Advertisements

About Priyanka Kapoor

Simple, Hardworking & friendly.....
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s