[英]How to handle AsyncTask failure
是否有一種特定的方法來處理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?
}
}
}
您可以簡單地將異常保存在字段中並在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();
}
}
}
}
我修改了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;
}
}
我一直在做的是創建一個新的Object(你可以稱之為AsyncTaskResult或任何你喜歡的東西),它可以通過doInBackground返回。 這個對象有兩件事:
然后我會將此對象返回到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
}
}
您可以通過創建AsyncTask
的子類來輕松地自己完成此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);
}
}
}
我結合了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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.