2011-08-20 140 views
10

是否有处理AsyncTask失败的具体方法?据我所知,唯一的办法就是用任务的返回值。如果可能,我希望能够提供有关失败的更多详细信息,并且null不是非常详细。如何处理AsyncTask失败

理想情况下,它会提供一个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? 
     } 
    }  
} 

回答

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(); 
      } 
     } 
    } 

}

+0

我喜欢这个答案,它非常简单。 – leech

+0

你为什么要检查空结果?它不会发生。 –

+0

没错,但是那个代码被修改了,原来有时会返回null。 –

2

我一直做的是创建一个新的对象(你可以叫它AsyncTaskResult或任何你喜欢),可以用doInBackground得到恢复。这个对象将有两件事情:

  1. 预期的结果(串在你的例子)
  2. 错误代码或者即使你想,异常物体本身或其包装版本。凡是基本上会帮你处理错误,如果任何发生

然后我将返回该对象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 
     } 
    } 

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); 
     } 
    } 
} 
+0

不认为,如果你想在UI线程中做一些事情,如果有异常抛出,这将工作。 – dongshengcn

+0

正确,这将在后台运行。 –

5

我修改尼古拉斯的代码一点,你应该想这样做在异常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; 
    } 
} 
+0

您应该检查'exception'是否为null而不是'result'。因为如果'realDoInBackground'返回null,那么'onException'将被调用并传递'null'。 – Jamol

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; 
     } 
    }