0

The Problem is:

My Activity starts an AsyncTask in onStart(). In the doInBackground Method I make a short webrequest, and depending on your network connetion, this may take a little, so I want this task cancelable...

BUT..

After hours of searching, testing and debugging I noticed now, when the user presses the back button during the doInBackground Method, the Keyevent ist always dispatched AFTER my doInBackground method is finished.

So I dont have to wonder why the asynctask never is cancelled when the users presses the backbutton, the AsyncTask.cancel(true) is invoked too late..... (even if I am not sure if cancel(true) will help)

So is this normal behavoiur with asynctask and backbutton?

This cant be normal, because how should the user ever get back from the activity on slow connection?

wait for timeout?

I am Begging for Help, cancel an async webrequest SHOULD be possible :)

VinoRosso
  • 102
  • 2
  • 9

2 Answers2

1

when the user presses the back button during the doInBackground Method, the Keyevent is always dispatched AFTER my doInBackground method is finished.

No, this isn't true.

If I hit the BACK button on my device when an AsyncTask is running in my main Activity (downloading files from my server), the Activity is immediately closed.

What IS true, however, is the AsyncTask will continue to run whatever code is in its doInBackground() method UNLESS I explicitly cancel it (but you kind of know that already).

As far as I can tell, your 'webrequest' (whatever that may be) is blocking your doInBackground() method and because of that, any attempt to cancel it in onPause(), onStop, onDestroy() etc will never work.

As advantej points out, the way the AsyncTask.cancel(...) method works is that it causes isCancelled to be set to 'true'. In order to successfully cancel the AsyncTask's doInBackground() method you need to periodically check isCancelled. Example...

@Override
protected Void doInBackground(String... params) {

    while (!isCancelled) {
        DoSomething();
    }
}

The problem is if DoSomething() (for example your 'webrequest') is blocking the while loop then isCancelled won't be checked until it completes.

Squonk
  • 48,735
  • 19
  • 103
  • 135
  • The Problem IS the KEYEVENT of the back Button is not dispatched UNTIL the doInBackground Method is finished. i did debug it and i can see it in the log, while doInBackground is running the log says : "waiting to dispatch key event" this cant be normal, im desperate. It has something to do with starting the Asynctask in the onStart() Method of the activity. but i have to start the AsyncTask somewhere..... – VinoRosso May 17 '11 at 08:48
  • @VinoRosso: "waiting to dispatch key event"...Where is that log entry created? Where (in your code) are you waiting to 'catch' the BACK button event? – Squonk May 17 '11 at 09:09
  • this log entry comes from the android os, when i Press the back button and doInBackground is running. In My Code i catch the Back Button event in onKeyDown. but this event comes too late. – VinoRosso May 17 '11 at 09:12
  • @VinoRosso: But where is your onKeyDown listener? You haven't posted any code so it is difficult to help solve this. – Squonk May 17 '11 at 09:17
  • Hers the Code:`@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { loader.cancel(true); super.onBackPressed(); } return super.onKeyDown(keyCode, event); }` – VinoRosso May 17 '11 at 09:25
  • @VinoRosso: OK...let's try again. You should be calling `loader.cancel(true)' in either onPause() or onStop() or onDestroy(). You don't need to 'trap' the BACK button press. The system will automatically 'finish' your Activity when the BACK button is pressed and you can cancel the AsyncTask in one of those methods. – Squonk May 17 '11 at 09:40
  • hmmkay sounds good, but since the back button press isnt dispatched until it wouldnt help me.... – VinoRosso May 17 '11 at 09:56
  • @VinoRosso: Sorry but I don't think I can help you further, you're not understanding what I'm trying to explain. Firstly, DO NOT try to 'trap' the BACK button press unless you know what you're doing. Secondly, as long as you DON'T 'trap' the BACK button press, the Activity WILL be finished which means going through those method calls and at any point you can call your 'cancel' (in onPause for example). My current app has 5 different activities which use AsyncTasks and they all cancel when I press the BACK button. – Squonk May 17 '11 at 10:12
  • Thanks for your help, i solved it now, i just didnt see it. Iam sorry for stealing your time, the backbutton press event did just not come through, because i was calling a synchronized method out of the doInBackground Method. after changing this, the event comes as expected and 'finish()' is called. So as conclusion, dont use synchronized methods out of doInBackground, but that should be clear :) – VinoRosso May 17 '11 at 11:14
0

This is the expected behavior. The documentation says :

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

advantej
  • 20,155
  • 4
  • 34
  • 39