16

I am using AsyncTask to perform some background calculations but I am unable to find a correct way to handle exceptions. Currently I am using the following code:

private class MyTask extends AsyncTask<String, Void, String>
{
    private int e = 0;

    @Override
    protected String doInBackground(String... params)
    {
        try
        {
            URL url = new URL("http://www.example.com/");
        }
        catch (MalformedURLException e)
        {
            e = 1;
        }

        // Other code here...

        return null;
    }

    @Override
    protected void onPostExecute(String result)
    {
        if (e == 1)
            Log.i("Some Tag", "An error occurred.");

        // Perform post processing here...
    }
}

I believe that the variable e maye be written/accessed by both the main and worker thread. As I know that onPostExecute() will only be run after doInBackround() has finished, can I omit any synchronization?

Is this bad code? Is there an agreed or correct way to handle exceptions in an AsyncTask?

Leo
  • 537
  • 1
  • 7
  • 16
  • 1
    possible duplicate of [AsyncTask and error handling on Android](http://stackoverflow.com/questions/1739515/asynctask-and-error-handling-on-android) – blahdiblah Apr 11 '12 at 19:35

3 Answers3

3

I've been doing that in my apps, I guess there is not a better way.

You can also read Mark Murphy answer about it.

Community
  • 1
  • 1
Macarse
  • 91,829
  • 44
  • 175
  • 230
3

I think your code would to the job but there is already some kind of error handling built into the AsyncTask class.

You can avoid to use an extra variable by using the cancel() method and its handler method onCancelled(). When you call cancel within the doInBackground() method the onCancelled method in the UI thread. Whether you call cancel(true) or cancel(false) depends on your needs.


private class MyTask extends AsyncTask<String, Void, String>
{    
    @Override
    protected NewsItem doInBackground(String... params)
    {
        try
        {
            URL url = new URL("http://www.example.com/");
        }
        catch (MalformedURLException e)
        {
            cancel(false/true);  
        }

        // Other code here...

        return null;
    }

    @Override
    protected void onPostExecute(String result)
    {              
        // Perform successful post processing here...
    }

   @Override
    protected void onCancelled() {
        super.onCancelled();
        // Perform error post processing here...
    }
}
Flo
  • 27,355
  • 15
  • 87
  • 125
  • This method only works if we have one type of exception. In my full code there are multiple things which can go wrong and they must be handled differently. – Leo Sep 12 '10 at 18:53
  • Why? You can add to the try-clause as much catch-class as u want. In each catch-statement u can call the cancel-Method. You also can catch(Exception e) which catches all types of Exceptions. Did I get u right, Leo? However, is it good practice to call cancel() when Exceptions are thrown or is there an other way of Exception handling implemented? – OneWorld Oct 12 '10 at 14:53
  • The cancel() way of handling the error is very close to what actually happens. Your processing has been canceled due to an error. You could still save some state on the ASyncTask that can be read by the UI thread to gain more information on what the error was. – DukeMe Feb 03 '15 at 21:01
2

This is guaranteed to work, even on SMP architecture. All the synchronization is done for you. It would however be better to use the return value to do this.

Romain Guy
  • 97,993
  • 18
  • 219
  • 200
  • 1
    In the actual code I am using a custom object as the return type which doesn't really lend itself to holding exception information. I assume I can't overload the `onPostExecute()` function very easily? – Leo Sep 11 '10 at 20:14
  • 4
    First of all, doInBackground must return an object of the same type as the parameter in onPostExecute(). Then you can just create a custom class to encapsulate the result + exception: class ResultHolder { Exception e; MyResult r; } – Romain Guy Sep 11 '10 at 21:18