Android Asynctask Example and Explanation

AsyncTask Android example

Ok, you are trying to access the GUI via another thread. This, in the main, is not good practice.

The AsyncTask executes everything in doInBackground() inside of another thread, which does not have access to the GUI where your views are.

preExecute() and postExecute() offer you access to the GUI before and after the heavy lifting occurs in this new thread, and you can even pass the result of the long operation to postExecute() to then show any results of processing.

See these lines where you are later updating your TextView:

TextView txt = findViewById(R.id.output);
txt.setText("Executed");

Put them in onPostExecute().

You will then see your TextView text updated after the doInBackground completes.

I noticed that your onClick listener does not check to see which View has been selected. I find the easiest way to do this is via switch statements. I have a complete class edited below with all suggestions to save confusion.

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;

public class AsyncTaskActivity extends Activity implements OnClickListener {

Button btn;
AsyncTask<?, ?, ?> runningTask;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = findViewById(R.id.button1);

// Because we implement OnClickListener, we only
// have to pass "this" (much easier)
btn.setOnClickListener(this);
}

@Override
public void onClick(View view) {
// Detect the view that was "clicked"
switch (view.getId()) {
case R.id.button1:
if (runningTask != null)
runningTask.cancel(true);
runningTask = new LongOperation();
runningTask.execute();
break;
}
}

@Override
protected void onDestroy() {
super.onDestroy();
// Cancel running task(s) to avoid memory leaks
if (runningTask != null)
runningTask.cancel(true);
}

private final class LongOperation extends AsyncTask<Void, Void, String> {

@Override
protected String doInBackground(Void... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// We were cancelled; stop sleeping!
}
}
return "Executed";
}

@Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed"); // txt.setText(result);
// You might want to change "executed" for the returned string
// passed into onPostExecute(), but that is up to you
}
}
}

Android AsyncTask example and explanation

AsyncTask is one of the easiest ways to implement parallelism in Android without having to deal with more complex methods like Threads. Though it offers a basic level of parallelism with the UI thread, it should not be used for longer operations (of, say, not more than 2 seconds).

AsyncTask has four methods

  • onPreExecute()
  • doInBackground()
  • onProgressUpdate()
  • onPostExecute()

where doInBackground() is the most important as it is where background computations are performed.

Code:

Here is a skeletal code outline with explanations:

public class AsyncTaskTestActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// This starts the AsyncTask
// Doesn't need to be in onCreate()
new MyTask().execute("my string parameter");
}

// Here is the AsyncTask class:
//
// AsyncTask<Params, Progress, Result>.
// Params – the type (Object/primitive) you pass to the AsyncTask from .execute()
// Progress – the type that gets passed to onProgressUpdate()
// Result – the type returns from doInBackground()
// Any of them can be String, Integer, Void, etc.

private class MyTask extends AsyncTask<String, Integer, String> {

// Runs in UI before background thread is called
@Override
protected void onPreExecute() {
super.onPreExecute();

// Do something like display a progress bar
}

// This is run in a background thread
@Override
protected String doInBackground(String... params) {
// get the string from params, which is an array
String myString = params[0];

// Do something that takes a long time, for example:
for (int i = 0; i <= 100; i++) {

// Do things

// Call this to update your progress
publishProgress(i);
}

return "this string is passed to onPostExecute";
}

// This is called from background thread but runs in UI
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);

// Do things like update the progress bar
}

// This runs in UI when background thread finishes
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);

// Do things like hide the progress bar or change a TextView
}
}
}

Flow Diagram:

Here is a diagram to help explain where all the parameters and types are going:

Sample Image

Other helpful links:

  • What arguments are passed into AsyncTask<arg1, arg2, arg3>?
  • Slidenerd Android AsyncTask Tutorial: Android Tutorial For Beginners
  • Understanding AsyncTask – Once and Forever
  • Dealing with AsyncTask and Screen Orientation
  • How to pass multiple parameters to AsynkTask
  • how to pass in two different data types to AsyncTask, Android

Using AsyncTask

It would be something like this

   public class TalkToServer extends AsyncTask<Void, Void, Void> {

@Override
protected void onPreExecute() {
/*
* do things before doInBackground() code runs
* such as preparing and showing a Dialog or ProgressBar
*/
}

@Override
protected void onProgressUpdate(Void... values) {
/*
* updating data
* such a Dialog or ProgressBar
*/

}

@Override
protected Void doInBackground(Void... params) {
//do your work here
return null;
}

@Override
protected void onPostExecute(Void result) {
/*
* do something with data here
* display it or send to mainactivity
* close any dialogs/ProgressBars/etc...
*/
}
}

Then you can execute it with

TalkToServer myTask = new MyTask(); // can add params for a constructor if needed
myTask.execute(); // here is where you would pass data to doInBackground()

You may not need onProgressUpdate() or onPreExecute() if you aren't using them to show a Dialog, progress, or other tasks before or during doInBackground().

onPreExecute() can be used to initialize and show a ProgressDialog. Then it could be dismissed in onPostExecute()

After a task finishes

onPostExecute() will be called. If the class is an inner-class of your Activity then you can update UI elements there or call a function to run code once the task finishes. If it is a separate file than the Activity then you can use an interface and create a callBack to the Activity and run code there once the task finishes.

This answer talks about using an interface for a callback if you need

Make sure any UI updating is done in any method besides doInBackground() or sent back to the Activity in any function besides doInBackground(). Heavy-lifting such as network operations should be done in doInBackground().

Also, be sure to read through the AsyncTask Docs completely. Especially the Threading Rules

How to use AsyncTask correctly in Android


import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;

public class AsyncExample extends Activity{


private String url="http://www.google.co.in";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}


@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();

new AsyncCaller().execute();

}

private class AsyncCaller extends AsyncTask<Void, Void, Void>
{
ProgressDialog pdLoading = new ProgressDialog(AsyncExample.this);

@Override
protected void onPreExecute() {
super.onPreExecute();

//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.show();
}
@Override
protected Void doInBackground(Void... params) {

//this method will be running on background thread so don't update UI frome here
//do your long running http tasks here,you dont want to pass argument and u can access the parent class' variable url over here


return null;
}

@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);

//this method will be running on UI thread

pdLoading.dismiss();
}

}
}

Can somebody explain how to use ASyncTask with Android?

AsyncTask uses parameterized types (java generics) so that you can specify the types it uses when you define your own AsyncTask. Perhaps it's easier to explain in this form:

public abstract class AsyncTask<Params, Progress, Result> {
...
protected abstract Result doInBackground(Params... params);

protected abstract void onProgressUpdate(Progress... progress);

protected abstract void onPostExecute(Result result);
...
}

There are no classes named Params, Progress, or Result. These are instead generic types. They are just placeholders for types you wish to use when you define your own AsyncTask subclass. The above could equally be written as such:

public abstract class AsyncTask<A, B, C> {
...
protected abstract C doInBackground(A... params);

protected abstract void onProgressUpdate(B... progress);

protected abstract void onPostExecute(C result);
...
}

Suppose I were defining an AsyncTask that takes a list of Strings representing URLs, and it will ping each one to see if it's reachable, then return the number that were reachable. Meanwhile, with each test, it will update a ProgressBar as each test completes. It might look something like this:

public class MyAsyncTask extends AsyncTask<String, Integer, Integer> {

@Override
protected Integer doInBackground(String... params) {
int total = params.length;
int successfulPings = 0;
for (int i = 0; i < total; i++) {
if (isReachable(params[i])) {
successfulPings++;
}
publishProgress(i, total);
}
return successfulPings;
}

@Override
protected void onProgressUpdate(Integer... progress) {
int testsSoFar = progress[0];
int totalTests = progress[1];
progressBar.setMax(totalTests);
progressBar.setProgress(testSoFar);
}

@Override
protected void onPostExecute(Integer result) {
Toast.makeTest(context, "Reached " + result + " sites.", Toast.LENGTH_SHORT).show();
}
}

I would initiate this as follows:

String[] urls = ...
MyAsyncTask task = new MyAsyncTask();
task.execute(urls);

The argument passed into execute will be passed into doInBackground. Whatever you do in doInBackground, you need to return something that gets passed in as the argument to onPostExecute. While in doInBackground, you can call publishProgress, where you can do something like I did (but you don't have to).

What arguments are passed into AsyncTask arg1, arg2, arg3 ?

Google's Android Documentation Says that :

An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.

AsyncTask's generic types :

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

Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the background computation.
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> { ... }

You Can further refer : http://developer.android.com/reference/android/os/AsyncTask.html

Or You Can clear whats the role of AsyncTask by refering Sankar-Ganesh's Blog

Well The structure of a typical AsyncTask class goes like :

private class MyTask extends AsyncTask<X, Y, Z>

protected void onPreExecute(){

}

This method is executed before starting the new Thread. There is no input/output values, so just initialize variables or whatever you think you need to do.

    protected Z doInBackground(X...x){

}

The most important method in the AsyncTask class. You have to place here all the stuff you want to do in the background, in a different thread from the main one. Here we have as an input value an array of objects from the type “X” (Do you see in the header? We have “...extends AsyncTask” These are the TYPES of the input parameters) and returns an object from the type “Z”.

   protected void onProgressUpdate(Y y){

}

This method is called using the method publishProgress(y) and it is usually used when you want to show any progress or information in the main screen, like a progress bar showing the progress of the operation you are doing in the background.

  protected void onPostExecute(Z z){

}

This method is called after the operation in the background is done. As an input parameter you will receive the output parameter of the doInBackground method.

What about the X, Y and Z types?

As you can deduce from the above structure:

 X – The type of the input variables value you want to set to the background process. This can be an array of objects.

Y – The type of the objects you are going to enter in the onProgressUpdate method.

Z – The type of the result from the operations you have done in the background process.

How do we call this task from an outside class? Just with the following two lines:

MyTask myTask = new MyTask();

myTask.execute(x);

Where x is the input parameter of the type X.

Once we have our task running, we can find out its status from “outside”. Using the “getStatus()” method.

 myTask.getStatus();

and we can receive the following status:

RUNNING - Indicates that the task is running.

PENDING - Indicates that the task has not been executed yet.

FINISHED - Indicates that onPostExecute(Z) has finished.

Hints about using AsyncTask

  1. Do not call the methods onPreExecute, doInBackground and onPostExecute manually. This is automatically done by the system.

  2. You cannot call an AsyncTask inside another AsyncTask or Thread. The call of the method execute must be done in the UI Thread.

  3. The method onPostExecute is executed in the UI Thread (here you can call another AsyncTask!).

  4. The input parameters of the task can be an Object array, this way you can put whatever objects and types you want.

how to pass in two different data types to AsyncTask, Android

You should create a constructor for that.

public class UpdateInfoAsyncTask extends AsyncTask<Void, Void, Void>{
int intValue;
String strValue;

public UpdateInfoAsyncTask(int intValue,String strValue){
this.intValue = intValue;
this.strValue = strValue;
}

@Override
protected void onPreExecute() {
// TODO Auto-generated method stub

}

@Override
protected Void doInBackground(Void... params) {
//use intValue
//use strValue
return null;
}
}

To use it

new UpdateInfoAsyncTask(10,"hi").execute();


Related Topics



Leave a reply



Submit