2
votes

I have some AsyncTasks downloading data from the network. If at a certain point I need to stop them, what is the best way to do it?
The documentation about:

task.cancel(mayInterruptIfRunning)

says:

Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.

Calling this method will result in onCancelled(Object) being invoked on the UI thread after doInBackground(Object[]) returns. Calling this method guarantees that onPostExecute(Object) is never invoked. After invoking this method, you should check the value returned by isCancelled() periodically from doInBackground(Object[]) to finish the task as early as possible.

From which I understood that ok, if mayInterruptIfRunning=true it tries to interrupt the thread but in the case it doesn't succeed one must check isCancelled() continuously on the background flow.
Here it comes the HTTP case. I read somewhere that Thread.interrupt doesn't actually interrupt IO operartions, however this is the case in which cancel() fails.
Therefore how to abort a download?

here some possibilities I thought:

  1. With ApacheHttp*: override the cancel(boolean) method and call in the new cancel(.) something like httpUriRequestInstance.abort().
  2. with HttpURLConnection: I can get the inputStream and fill in a while another buffered outputstream so as to check periodically a flag associated to isCancelled(). I mean something like:

    ... httpURLConnection code which creates an HttpURLConnection "conn"  
    InputStream in = conn.getInputStream();  
    ByteArrayOutputStream baos = new ByteArrayOutputStream(defSize);   
    byte[] buff = new byte[buffSize];  
    int br;  
    while( (br = in.read(buff) ) >-1){  
      if(cancelled) return null; //eventually closing th inpustream  
     baos.write(buffer,0,br);  
    }  
    // ...  
    

what do you suggest?

1

1 Answers

4
votes

I'd definitely go with HttpURLConnection. And possibly would do something like:

  1. Add a public void cancel() method to my custom AsyncTask implementation
  2. Implement cancel() as

    public void cancel() { this.cancel(true); mConnection.disconnect(); // TODO try close input stream }

  3. From my activity call mMyAsyncTask.cancel() when required