Catch AsyncTask exception. Need a thought

I want to catch a stream exception in doInBackground and print an error message in onPostExcecute. The problem is that I don't have a Throwable object in onPostExecute. How to catch an exception in a thread without a user interface and print an error message in the user interface ?

public class TestTask extends AsyncTask<Void, Void, List<String>> { @Override protected List<String> doInBackground(final Void... params) { try { ... return listOfString; } catch(SomeCustomException e) { ... return null; } } @Override protected void onPostExecute(final List<String> result) { if(result == null) { // print the error of the Throwable "e". // The problem is I don't have the Throwable object here! So I can't check the type of exception. } } } 

Update after Arun's answer:

This is my AsyncTask wrapper class. He intends to do Exception handling in doInBackground, but I cannot find a suitable solution for this.

 public abstract class AbstractWorkerTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> implements Workable { protected OnPreExecuteListener onPreExecuteListener; protected OnPostExecuteListener<Result> onPostExecuteListener; protected ExceptionHappenedListener exceptionHappendedListener; private boolean working; @Override protected void onPreExecute() { if (onPreExecuteListener != null) { onPreExecuteListener.onPreExecute(); } working = true; } @Override protected void onPostExecute(final Result result) { working = false; if(/* .........*/ ) { exceptionHappendedListener.exceptionHappended(e); } if (onPostExecuteListener != null) { onPostExecuteListener.onPostExecute(result); } } @Override public boolean isWorking() { return working; } public void setOnPreExecuteListener(final OnPreExecuteListener onPreExecuteListener) { this.onPreExecuteListener = onPreExecuteListener; } public void setOnPostExecuteListener(final OnPostExecuteListener<Result> onPostExecuteListener) { this.onPostExecuteListener = onPostExecuteListener; } public void setExceptionHappendedListener(final ExceptionHappenedListener exceptionHappendedListener) { this.exceptionHappendedListener = exceptionHappendedListener; } public interface OnPreExecuteListener { void onPreExecute(); } public interface OnPostExecuteListener<Result> { void onPostExecute(final Result result); } public interface ExceptionHappenedListener { void exceptionHappended(Exception e); } } 
+8
android exception-handling
source share
3 answers

Change the return type of doInBackground() to Object , and when you get the result in onPostExecute(Object result) , use the instanceOf operator to check if the returned result is Exception or List<String> .

Edit

Since the result can be either an Exception or a valid list, you can use the following:

 protected void onPostExecute(final Object result) { working = false; if(result instanceof SomeCustomException) { exceptionHappendedListener.exceptionHappended(result); } else{ if (onPostExecuteListener != null) { onPostExecuteListener.onPostExecute(result); } } } 

Also modify the following statement:

 public abstract class AbstractWorkerTask<Params, Progress, Object> extends AsyncTask<Params, Progress, Object> 
+7
source share

Just save the exception to the list and handle it later, since onPostExecute () is always called after doInBackground ():

 public class TestTask extends AsyncTask<Params, Progress, Result> { List<Exception> exceptions = new ArrayList<Exception>(); @Override protected Result doInBackground(Params... params) { try { ... } catch(SomeCustomException e) { exceptions.add(e); } return result; } @Override protected void onPostExecute(Result result) { for (Exception e : exceptions) { // Do whatever you want for the exception here ... } } } 

This is doable, but rarely used, as in most cases, we want to handle the exception as soon as it is thrown and thrown:

 public class TestTask extends AsyncTask<Params, Progress, Result> { @Override protected Result doInBackground(Params... params) { try { ... } catch(SomeCustomException e) { // If you need update UI, simply do this: runOnUiThread(new Runnable() { public void run() { // update your UI component here. myTextView.setText("Exception!!!"); } }); } return result; } } 

Hope this makes sense.

+4
source share

Changing the doInBackground return type to Object to pass an Exception and then use instanceof() is a source of code smell (bad programming practice). It is always preferable to limit the type of the return value to what you want to return.

Based on this answer, simply add a private element to save the exception sent to doInBackground , and then check it first on onPostExecute .

Only one Exception should be caught, because you must immediately stop doing doInBackground after the exception is thrown and handle it gracefully in onPostExecute , where you have access to the user interface elements, and therefore can inform the user about the failure.

General example (AsyncTask body):

 private Exception mException @Override protected Result doInBackground(Params... params) { try { // --- Do something --- // } catch( SomeException e ){ mException = e; return null; } } @Override protected void onPostExecute(Result result) { if (mException != null) { // --- handle exception --- // return; } // --- Perform normal post execution actions --- // } 
+4
source share

All Articles