0

I need to cancel my asyncthread . In my application I am doing some heavy calculations, and I want to give user ability to cancel calculations(and then retry). I read on forums, that you can't just stop task from what is it doing, and that you need to check if task isCancelled=true inside your DoinBackground code. But that doesn't work for me.

Task itself is working great and it outputs correct data if I leaved it to end on itself.

In my App first I call function naredi_pdf_start(view), then when the task is running, if I call close_pdf1(view), it gives me an error.(I am changing views and app can't find my pdf_text1 Textview when calling publishProgress- null pointer exception). I really dont know how to use task.cancel(true) method (in my case: start_pdf.cancel(true))).

Here is my code:

String progress_pdf;
naredi_pdf start_pdf;

public void naredi_pdf_start(View view) {
    start_pdf=new naredi_pdf();
    start_pdf.execute();
}

public void close_pdf1(View view) {

    if(start_pdf!=null) {
        Log.v("not null","not null");

        start_pdf.cancel(true);
        setContentView(R.layout.other_view); //This is where 
                                             //I don't have TextView pdf_text1
    }
}

private class naredi_pdf extends AsyncTask<Void, String, Void> {

    protected Void doInBackground( Void... ignoredParams ) {
        progress_pdf="Calculating Statistical Data";

        //A LOT OF CODING

        for(int i = 0; i < 1; i++) {
            if(isCancelled()) {
                break;
            }
            else {
                publishProgress("Calculating team statistics");  
            }
        }

        //MORE OF CODING              

        for (int i = 0; i < 1; i++) {
            if (isCancelled()) {
                break;
            }
            else {
                publishProgress("Calculating player's BIO");  
            }
        }

        //MORE OF CODING       

        for (int i = 0; i < 1; i++) {
            if (isCancelled()) {
                break;
            }
        else {
                publishProgress("Calculating player's individual performance");
            }
        }

        return null; 
    }

    protected void onPostExecute( Void array ) {
        //saving to database
    }

    protected void onProgressUpdate(String... values) {
        progress_pdf=values[0]+"\n"+progress_pdf;

        if (isCancelled())  {

        }
        else {
            TextView pdf_text1 = (TextView) findViewById (R.id.pdf_text1);
            pdf_text1.setText(progress_pdf);
            // dialog(view);
        }
    }
}
Ole
  • 7,899
  • 2
  • 29
  • 34
Gregor
  • 275
  • 1
  • 7
  • 19

3 Answers3

2

The return statement cancels the execution of the doInBackground method, not break.

Rezoom
  • 183
  • 1
  • 7
  • 1
    He breaks the `for`-loops and will eventually hit `return null`. It works, although returning null right away would be better :) – Ole Jan 11 '13 at 14:40
  • Yes my code looks weird - it would be better to have return null... But It is just me, but I think that "return null" does'nt stop the doInBackground function... – Gregor Jan 11 '13 at 15:30
  • `return` always stops the execution of a java method. Like Ole mentioned `onCancelled()` is invoked instead of `onPostExecute()` after an `AsyncTask` is canceled and the execution of `doInBackground()` has finished. – Rezoom Jan 11 '13 at 15:39
2

Your problem is not that you can't cancel the AsyncTask. You probably get NullPointerException because your call to setContentView() goes through before AsyncTask.cancel() has been successful. A onProgressUpdate() gets called, only to find that the layout is now changed and there is no Viewwith id=R.id.pdf_text1!

From documentation on AsyncTask.

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.)

Since onCancelled() runs on the UI thread, and you are certain that no subsequent calls to onProgressUpdate() will occure, it's is a great place to call setContentView().

Override onCancelled() in you AsyncTask

private class naredi_pdf extends AsyncTask<Void, String, Void> {

    protected Void doInBackground( Void... ignoredParams ) { // YOUR CODE HERE}
    protected void onPostExecute( Void array ) { // YOUR CODE HERE}
    protected void onProgressUpdate(String... values) {// YOUR CODE HERE}

    // ADD THIS
    @Override
    protected void onCancelled() {
        // Do not call super.onCancelled()!

        // Set the new layout
        setContentView(R.id.other_layout);
    }
}

Change close_pdf1()

public void close_pdf1(View view) {
    if(start_pdf!=null) {
        Log.v("not null","not null");

        start_pdf.cancel(true);
    }
}

And you should have an AsyncTask that automatically changes your layout when cancelled. Hopefully you should not encounter any NullPointerException either. Haven't tried the code though :)

Edit

If you feel fancy, follow Rezooms advice on using return.

for(int i = 0; i < 1; i++) {
    if(isCancelled()) {
        return null;
    }
    .
    .
    .
}
Ole
  • 7,899
  • 2
  • 29
  • 34
0

isCancelled is a propietary method of AsyncTask class.

You should define a private boolean property on your extended class, do something like this

private class myAsyncTask extends AsyncTask<Void, String, Void> {
          private boolean isTaskCancelled = false;

          public void cancelTask(){
               isTaskCancelled = true;
          }

          private boolean isTaskCancelled(){
               return isTaskCancelled;
          }

          protected Void doInBackground( Void... ignoredParams ) {
            //Do some stuff
             if (isTaskCancelled()){
                return;
             }
          }


          protected void onPostExecute( Void array )
          {
           //Do something
          }



          protected void onProgressUpdate(String... values)
          {
           //Do something
          }
    }
noni
  • 2,927
  • 19
  • 18