是否有一种特定的方法来处理AsyncTask中的故障?据我所知,唯一的方法是使用任务的返回值。如果可能的话,我希望能够提供有关失败的更多细节,并且null不是很冗长。
理想情况下,它会提供一个onError处理程序,但我不认为它有一个。
class DownloadAsyncTask extends AsyncTask<String, Void, String> {
/** this would be cool if it existed */
@Override
protected void onError(Exception ex) {
...
}
@Override
protected String doInBackground(String... params) {
try {
... download ...
} catch (IOException e) {
setError(e); // maybe like this?
}
}
}
答案 0 :(得分:18)
您可以简单地将异常保存在字段中并在onPostExecute()
中进行检查(以确保在UI线程上运行任何错误处理代码)。类似的东西:
new AsyncTask<Void, Void, Boolean>() {
Exception error;
@Override
protected Boolean doInBackground(Void... params) {
try {
// do work
return true;
} catch (Exception e) {
error = e;
return false;
}
}
@Override
protected void onPostExecute(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();
}
}
}
}
答案 1 :(得分:5)
我修改了Nicholas的代码,如果你想在异常的UI线程中做一些事情。
请记住AsyncTask只能在实例化后执行一次。
class ErrorHandlingAsyncTask extends AsyncTask<..., ..., ...> {
private Exception exception = null;
protected abstract void onResult(Result result);
protected abstract void onException(Exception e);
protected abstract ... realDoInBackground(...);
@Override
final protected void onPostExecute(Result result) {
if(result != null) {
onResult(result);
} else {
onException(exception);
}
}
@Override
protected ... doInBackground(...) {
try {
return realDoInBackground(...);
} catch(Exception e) {
exception = e;
}
return null;
}
}
答案 2 :(得分:2)
我一直在做的是创建一个可以通过doInBackground返回的新对象(可以称之为AsyncTaskResult或任何你喜欢的)。这个对象有两件事:
然后我将这个对象返回到postExecute()并让该方法检查错误,如果有,那么我会相应地处理它,否则我采取预期的结果并对它做任何事情。
对象将是:
public class AsyncTaskResult<T extends Object> {
Exception exception;
T asyncTaskResult;
public void setResult(T asyncTaskResult) {
this.asyncTaskResult = asyncTaskResult;
}
public T getResult() {
return asyncTaskResult;
}
public void setException(Exception exception) {
this.exception = exception;
}
public boolean hasException() {
return exception != null;
}
public Exception getException() {
return exception;
}
}
您的代码变为:
/** this would be cool if it existed */
protected void onError(Exception ex) {
// handle error...
}
@Override
protected AsyncTaskResult<String> doInBackground(String... params) {
AsyncTaskResult<String> result = new AsyncTaskResult<String>();
try {
// ... download ...
} catch (IOException e) {
result.setException(e);
}
return result;
}
@Override
protected void onPostExecute(AsyncTaskResult<String> result) {
if(result.hasException()) {
// handle error here...
onError(result.getException());
} else {
// deal with the result
}
}
答案 3 :(得分:2)
您可以通过创建AsyncTask
的子类来轻松完成此操作。也许像ErrorHandlingAsyncTask
这样的东西。首先创建一个抽象回调方法onException(Exception e)
。您的doInBackground(Generic... params)
方法应将其所有代码包装在try-catch
块中。在catch
区块中,呼叫onException(Exception e)
传递您的例外情况。
现在,当您需要此功能时,只需覆盖新的ErrorHandlingAsyncTask类。
快速而脏的伪代码:
class ErrorHandlingAsyncTask extends AsyncTask<..., ..., ...> {
protected abstract void onException(Exception e);
protected abstract ... realDoInBackground(...);
protected ... doInBackground(...) {
try {
return realDoInBackground(...);
} catch(Exception e) {
onException(e);
}
}
}
答案 4 :(得分:0)
我结合了momo和Dongshengcn的答案,并创建了我自己的基类,包括后台和前台异常处理(如果你想做一些严重的错误记录)
问题是,我的代码封装了所有ResultOrError类的东西,只是让你返回正常结果或抛出异常
public abstract class HandledAsyncTask<Params, Progress, Result> extends
AsyncTask<Params, Progress, ResultOrException<Result>> {
/**
* Wraps the calling of the {@link #doTask(Object[])} method, also handling
* the exceptions possibly thrown.
*/
protected final ResultOrException<Result> doInBackground(Params... params) {
try {
Result res = doTask(params);
return new ResultOrException<Result>(res);
} catch (Exception e) {
onBackgroundException(e);
return new 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.
*/
protected abstract Result doTask(Params[] params);
/**
* Handles calling the {@link #onSuccess(Object)} and
* {@link #onFailure(Exception)} methods.
*/
@Override
protected final void 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
*/
protected void onBackgroundException(Exception exception) {
}
/**
* Called when the {@link #doTask(Object[])} method finished executing with
* no exceptions thrown.
*
* @param result
* The result returned from {@link #doTask(Object[])}
*/
protected void onSuccess(Result result) {
}
/**
* Called when an exception was thrown in {@link #doTask(Object[])}. Handled
* in the foreground thread.
*
* @param exception
* The thrown exception
*/
protected void onFailure(Exception exception) {
}
}
class ResultOrException<TResult> {
/**
* The possibly thrown exception
*/
Exception mException;
/**
* The result, if no exception was thrown
*/
TResult mResult;
/**
* @param exception
* The thrown exception
*/
public ResultOrException(Exception exception) {
mException = exception;
}
/**
* @param result
* The result returned from the method
*/
public ResultOrException(TResult result) {
mResult = result;
}
/**
* @return the exception
*/
public Exception getException() {
return mException;
}
/**
* @param exception
* the exception to set
*/
public void setException(Exception exception) {
mException = exception;
}
/**
* @return the result
*/
public TResult getResult() {
return mResult;
}
/**
* @param result
* the result to set
*/
public void setResult(TResult result) {
mResult = result;
}
}