Monday, 6 January 2014

Android Asynctask… is this the correct way to do it?


CounterTask.java:
package my.tasks;

import java.util.Random;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.util.Log;

/**
 * @author 2
 * 
 *         Simulates a time consuming task, counts in the background from 0 to
 *         the given value in first parameter. Its progress is published via an
 *         integer which is a percentual value 0..100. The task may not
 *         complete, it may fail or it may be cancelled by the user. In case of
 *         success it returns true.
 */
public class CounterTask extends AsyncTask<Integer, Integer, Boolean> {

private static final long DELAY = 100;
private static final int PROBABILITY_TO_FAIL_EVERY_STEP = 1;
private static final String TAG = "CounterTask";
private ProgressDialog progressDialog;
private Random random;

/**
 * @param progressDialog
 *            a ProgressDialog the task can use to display its progress.
 */
public CounterTask(ProgressDialog progressDialog) {
    this.progressDialog = progressDialog;
    this.progressDialog.setMax(100);
    this.random = new Random();
}

/*
 * (non-Javadoc)
 * 
 * @see android.os.AsyncTask#doInBackground(Params[])
 * 
 * Set params[0] to the maximum value you want the task to count to.
 */
@Override
protected Boolean doInBackground(Integer... params) {
    validateParams(params);
    int count_max = params[0];

    for (int i = 0; i < count_max; i++) {
        int progressPercent = calculateProgressPercent(i, count_max);
        publishProgress(progressPercent);
        Log.i(TAG, "Counter: " + Integer.toString(i));
        Log.i(TAG, "Progress published: " + Integer.toString(progressPercent) + "%");
        if (sleep() == false) {
            return false;
        }
        if (doesFail(PROBABILITY_TO_FAIL_EVERY_STEP)) {
            Log.i(TAG, "Background fails.");
            return false;
        }
    }

    Log.i(TAG, "Background succeeds.");
    return true;
}

@Override
protected void onCancelled() {
    super.onCancelled();
    Log.i(TAG, "Background cancelled.");
}

@Override
protected void onPostExecute(Boolean result) {
    super.onPostExecute(result);
    progressDialog.dismiss();

    String message = null;
    if (result)
        message = "Background succeeded.";
    else
        message = "Background failed.";
    Log.i(TAG, message);
    createAlertDialog(message).show();
}

private Dialog createAlertDialog(String message) {
    AlertDialog.Builder builder = new Builder(progressDialog.getContext());
    AlertDialog dialog = builder.setMessage(message).setTitle("Result").setCancelable(true).create();
    return dialog;
}

@Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    progressDialog.setProgress(values[0]);
}

/**
 * Helper method to decide if the task fails in this step.
 * 
 * @param probabilityToFail
 *            Value 0..100 the probability to fail.
 * @return true if it fails, false if not
 */
private boolean doesFail(int probabilityToFail) {

    int prob = random.nextInt(100);
    if (prob < probabilityToFail)
        return true;
    else
        return false;
}

/**
 * The thread sleeps from step to step to simulate a time consuming task.
 * 
 * @return
 */
private boolean sleep() {
    try {
        Thread.sleep(DELAY);
    } catch (InterruptedException e) {
        return false;
    }
    return true;
}

private int calculateProgressPercent(int done, int max) {
    done = done * 100;
    return done / max;
}

private void validateParams(Integer... integers) {
    if (integers == null || integers.length != 1 || integers[0] < 0)
        throw new IllegalArgumentException();
}
}





MainActivity.java:
package my.application;

import my.tasks.CounterTask;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener, OnCancelListener {

private CounterTask counterTask;

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

    Button startButton = (Button) findViewById(R.id.startButton);
    startButton.setOnClickListener(this);
}

@Override
public void onClick(View view) {
    int id = view.getId();

    switch (id) {
    case R.id.startButton:
        ProgressDialog progressDialog = createProgressDialog();
        progressDialog.show();
        CounterTask ct = new CounterTask(progressDialog);
        counterTask = (CounterTask) ct.execute(100);
        break;

    default:
        break;
    }
}

private ProgressDialog createProgressDialog() {

    ProgressDialog progressDialog = new ProgressDialog(this);
    progressDialog.setProgress(0);
    progressDialog.setMax(100);
    progressDialog.setTitle("Progress");
    progressDialog.setCancelable(true);
    progressDialog.setOnCancelListener(this);
    progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    return progressDialog;

}

@Override
public void onCancel(DialogInterface arg0) {
    counterTask.cancel(true);
}

}

No comments:

Post a Comment