2011-08-20 17 views
10

क्या AsyncTask में विफलता को संभालने का कोई विशिष्ट तरीका है? जहां तक ​​मैं एकमात्र तरीका बता सकता हूं कार्य के वापसी मूल्य के साथ है। यदि संभव हो तो मैं विफलता पर अधिक जानकारी प्रदान करने में सक्षम होना चाहता हूं, और शून्य बहुत वर्बोज़ नहीं है।AsyncTask विफलता को कैसे संभालें

आदर्श रूप से यह एक ऑनर हैंडलर प्रदान करेगा, लेकिन मुझे नहीं लगता कि इसमें एक है।

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() में यह जांच कर सकते हैं (यह सुनिश्चित करें कि कोड से निपटने के किसी भी त्रुटि यूआई धागे पर चलाया जाता है)। की तरह कुछ:

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

ठीक है, लेकिन वह कोड अनुकूलित किया गया था, मूल कभी-कभी शून्य वापस आ जाता है। –

2

क्या मैं हमेशा एक नई वस्तु बनाने है कि doInBackground के साथ वापस आ प्राप्त कर सकते हैं (यदि आप इसे AsyncTaskResult या जो कुछ भी आप की तरह कॉल कर सकते हैं)। (अपने उदाहरण में स्ट्रिंग)

  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) पर जाकर कॉल करें।

अब, जब आपको इस कार्यक्षमता की आवश्यकता है, तो बस अपनी नई त्रुटि हैडलिंगएसिंक टास्क क्लास को ओवरराइड करें।

त्वरित और गंदे छद्म कोड:

class ErrorHandlingAsyncTask extends AsyncTask<..., ..., ...> { 
    protected abstract void onException(Exception e); 

    protected abstract ... realDoInBackground(...); 

    protected ... doInBackground(...) { 
     try { 
      return realDoInBackground(...); 
     } catch(Exception e) { 
      onException(e); 
     } 
    } 
} 
+0

नहीं लगता है कि यह अगर तुम यूआई धागा भीतर कुछ करने के लिए अगर वहाँ अपवाद है चाहता हूँ काम करेंगे है। – dongshengcn

+0

सही, यह पृष्ठभूमि में चलाया जाएगा। –

5

मैं थोड़ा निकोलस के कोड को संशोधित किया है, तो आप अपवाद में यूआई सूत्र में कुछ करना चाहता हूँ चाहिए।

याद रखें कि 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

आपको यह जांचना चाहिए कि 'परिणाम' के बजाय 'अपवाद' शून्य है या नहीं। क्योंकि यदि 'realDoInBackground' शून्य लौटाता है, तो' अपवाद 'को बुलाया जाएगा और' शून्य 'पारित किया जाएगा। – Jamol

0

मैं मोमो की और 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; 
     } 
    } 
संबंधित मुद्दे