How To Handle Asynctask Failure
Solution 1:
You can simply save the exception in a field and check it in onPostExecute()
(to ensure that any error handling code is run on the UI thread). Something like:
newAsyncTask<Void, Void, Boolean>() {
Exception error;
@OverrideprotectedBooleandoInBackground(Void... params) {
try {
// do workreturntrue;
} catch (Exception e) {
error = e;
returnfalse;
}
}
@OverrideprotectedvoidonPostExecute(Boolean result) {
if (result) {
Toast.makeText(ctx, "Success!",
Toast.LENGTH_SHORT).show();
} else {
if (error != null) {
Toast.makeText(ctx, error.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
}
}
Solution 2:
I modified Nicholas's code a bit, should you want to do something in the UI thread in exception.
Remember the AsyncTask can only be executed once after instantiated.
classErrorHandlingAsyncTaskextendsAsyncTask<..., ..., ...> {
privateExceptionexception=null;
protectedabstractvoidonResult(Result result);
protectedabstractvoidonException(Exception e);
protectedabstract ... realDoInBackground(...);
@OverridefinalprotectedvoidonPostExecute(Result result) {
if(result != null) {
onResult(result);
} else {
onException(exception);
}
}
@Overrideprotected ... doInBackground(...) {
try {
return realDoInBackground(...);
} catch(Exception e) {
exception = e;
}
returnnull;
}
}
Solution 3:
You can do this yourself pretty easily by creating a subclass of AsyncTask
. Perhaps something like ErrorHandlingAsyncTask
. First create an abstract callback method onException(Exception e)
. Your doInBackground(Generic... params)
method should wrap all of its code in a try-catch
block. In the catch
block, call out to onException(Exception e)
passing in your exception.
Now, when you need this functionality, just override your new ErrorHandlingAsyncTask class.
Quick and dirty pseudo code:
classErrorHandlingAsyncTaskextendsAsyncTask<..., ..., ...> {
protectedabstractvoid onException(Exception e);
protectedabstract ... realDoInBackground(...);
protected ... doInBackground(...) {
try {
return realDoInBackground(...);
} catch(Exception e) {
onException(e);
}
}
}
Solution 4:
What I always do is create a new Object (you can call it AsyncTaskResult or whatever you like) that can get returned with doInBackground. This Object would have two things:
- The expected result (String in your example)
- Error code or even if you want, the Exception object itself or a wrapped version of it. Anything that basically will help you handling error if any occurs
I would then return this object to postExecute() and let that method check for the error, if there is then I handle it accordingly, otherwise I take the expected result and do whatever with it.
The object would be something like:
publicclassAsyncTaskResult<T extendsObject> {
Exception exception;
T asyncTaskResult;
publicvoidsetResult(T asyncTaskResult) {
this.asyncTaskResult = asyncTaskResult;
}
public T getResult() {
return asyncTaskResult;
}
publicvoidsetException(Exception exception) {
this.exception = exception;
}
publicbooleanhasException() {
return exception != null;
}
publicExceptiongetException() {
return exception;
}
}
And your code becomes :
/** this would be cool if it existed */protectedvoidonError(Exception ex) {
// handle error...
}
@OverrideprotectedAsyncTaskResult<String> doInBackground(String... params) {
AsyncTaskResult<String> result = newAsyncTaskResult<String>();
try {
// ... download ...
} catch (IOException e) {
result.setException(e);
}
return result;
}
@OverrideprotectedvoidonPostExecute(AsyncTaskResult<String> result) {
if(result.hasException()) {
// handle error here...onError(result.getException());
} else {
// deal with the result
}
}
Solution 5:
I combined momo's and Dongshengcn's answers, and created my own base class with both background and foreground exception handling (in case you want to do some serious error logging)
The thing is, my code encapsulates all of the ResultOrError class stuff and simply lets you return the normal result or throw an exception
publicabstractclassHandledAsyncTask<Params, Progress, Result> extendsAsyncTask<Params, Progress, ResultOrException<Result>> {
/**
* Wraps the calling of the {@link #doTask(Object[])} method, also handling
* the exceptions possibly thrown.
*/protectedfinal ResultOrException<Result> doInBackground(Params... params) {
try {
Result res = doTask(params);
returnnew ResultOrException<Result>(res);
} catch (Exception e) {
onBackgroundException(e);
returnnew ResultOrException<Result>(e);
}
}
/**
* Override this method to perform a computation on a background thread. The
* specified parameters are the parameters passed to
* {@link #doTask(Object[])} by the caller of this task. This method can
* call {@link #publishProgress(Object...)} to publish updates on the UI
* thread.
*
* @param params
* The parameters of the task.
* @return A result, defined by the subclass of this task.
*/protectedabstract Result doTask(Params[] params);
/**
* Handles calling the {@link #onSuccess(Object)} and
* {@link #onFailure(Exception)} methods.
*/
@Override
protectedfinalvoid onPostExecute(ResultOrException<Result> result) {
if (result.getException() != null) {
onFailure(result.getException());
} else {
onSuccess(result.getResult());
}
}
/**
* Called when an exception was thrown in {@link #doTask(Object[])}. Handled
* in the background thread.
*
* @param exception
* The thrown exception
*/protectedvoid onBackgroundException(Exceptionexception) {
}
/**
* Called when the {@link #doTask(Object[])} method finished executing with
* no exceptions thrown.
*
* @param result
* The result returned from {@link #doTask(Object[])}
*/protectedvoid onSuccess(Result result) {
}
/**
* Called when an exception was thrown in {@link #doTask(Object[])}. Handled
* in the foreground thread.
*
* @param exception
* The thrown exception
*/protectedvoid onFailure(Exceptionexception) {
}
}
classResultOrException<TResult> {
/**
* The possibly thrown exception
*/Exception mException;
/**
* The result, if no exception was thrown
*/
TResult mResult;
/**
* @param exception
* The thrown exception
*/public ResultOrException(Exceptionexception) {
mException = exception;
}
/**
* @param result
* The result returned from the method
*/public ResultOrException(TResult result) {
mResult = result;
}
/**
* @return the exception
*/publicException getException() {
return mException;
}
/**
* @param exception
* the exception to set
*/publicvoid setException(Exceptionexception) {
mException = exception;
}
/**
* @return the result
*/public TResult getResult() {
return mResult;
}
/**
* @param result
* the result to set
*/publicvoid setResult(TResult result) {
mResult = result;
}
}
Post a Comment for "How To Handle Asynctask Failure"