2012-06-08 91 views
8

我想捕獲doInBackground中線程的異常,並在onPostExcecute中輸出錯誤消息。問題是我沒有onPostExecute中的Throwable對象。如何在非UI線程中捕獲異常在UI線程中打印錯誤消息?阿倫的回答後AsyncTask的捕獲異常。需要思考

public class TestTask extends AsyncTask<Void, Void, List<String>> { 

    @Override 
    protected List<String> doInBackground(final Void... params) { 
     try { 
      ... 
      return listOfString; 
     } catch(SomeCustomException e) { 
      ... 
      return null; 
     }  
    } 

    @Override 
    protected void onPostExecute(final List<String> result) { 
     if(result == null) { 
      // print the error of the Throwable "e". 
      // The problem is I don't have the Throwable object here! So I can't check the type of exception. 
     } 

    } 
} 

更新:

這是我的AsyncTask包裝類。它打算在doInBackground中處理異常,但我找不到一個好的解決方案。

public abstract class AbstractWorkerTask<Params, Progress, Result> 
extends AsyncTask<Params, Progress, Result> 
implements Workable { 
    protected OnPreExecuteListener onPreExecuteListener; 
    protected OnPostExecuteListener<Result> onPostExecuteListener; 
    protected ExceptionHappenedListener exceptionHappendedListener; 
    private boolean working; 

    @Override 
    protected void onPreExecute() { 
     if (onPreExecuteListener != null) { 
      onPreExecuteListener.onPreExecute(); 
     } 
     working = true; 
    } 

    @Override 
    protected void onPostExecute(final Result result) { 
     working = false; 
     if(/* .........*/) { 
      exceptionHappendedListener.exceptionHappended(e); 
     } 
     if (onPostExecuteListener != null) { 
      onPostExecuteListener.onPostExecute(result); 
     } 
    } 

    @Override 
    public boolean isWorking() { 
     return working; 
    } 

    public void setOnPreExecuteListener(final OnPreExecuteListener onPreExecuteListener) { 
     this.onPreExecuteListener = onPreExecuteListener; 
    } 

    public void setOnPostExecuteListener(final OnPostExecuteListener<Result> onPostExecuteListener) { 
     this.onPostExecuteListener = onPostExecuteListener; 
    } 

    public void setExceptionHappendedListener(final ExceptionHappenedListener exceptionHappendedListener) { 
     this.exceptionHappendedListener = exceptionHappendedListener; 
    } 

    public interface OnPreExecuteListener { 
     void onPreExecute(); 
    } 

    public interface OnPostExecuteListener<Result> { 
     void onPostExecute(final Result result); 
    } 

    public interface ExceptionHappenedListener { 
     void exceptionHappended(Exception e); 
    } 
} 
+0

可以實現某種回調的設置和獲取錯誤。 –

+0

我試過了,但是我不能在doInBackground中返回Exception和List 。怎麼做? – Emerald214

+0

嘗試從'doInBackground()'的'catch'返回'e.toString()'而不是'null' ... – GAMA

回答

7

變化doInBackground()Object,當你收到onPostExecute(Object result)結果使用instanceOf操作的返回類型,以檢查返回的結果是一個ExceptionList<String>

編輯

由於結果可以是異常或其他適當的列表,你可以使用以下命令:

protected void onPostExecute(final Object result) { 
    working = false; 
    if(result instanceof SomeCustomException) { 
     exceptionHappendedListener.exceptionHappended(result); 
    } 
    else{ 
     if (onPostExecuteListener != null) { 
      onPostExecuteListener.onPostExecute(result); 
     } 
    } 
} 

也改變了以下聲明:

public abstract class AbstractWorkerTask<Params, Progress, Object> extends AsyncTask<Params, Progress, Object> 
+0

這很好但不解決問題,因爲你不能instanceof參數化類型(列表)。 :[ – Emerald214

4

將異常存儲到列表中並稍後處理,因爲onPostExecute()始終在doInBackground()後調用:

public class TestTask extends AsyncTask<Params, Progress, Result> { 

    List<Exception> exceptions = new ArrayList<Exception>(); 

    @Override 
    protected Result doInBackground(Params... params) { 
    try { 
     ... 
    } catch(SomeCustomException e) { 
     exceptions.add(e); 
    } 
    return result; 
    } 

    @Override 
    protected void onPostExecute(Result result) { 
    for (Exception e : exceptions) { 
     // Do whatever you want for the exception here 
     ... 
    } 
    } 

} 

這是可行的,但很少使用,因爲在大多數情況下,我們希望儘快處理異常,因爲它拋出,並逮住:

public class TestTask extends AsyncTask<Params, Progress, Result> { 

    @Override 
    protected Result doInBackground(Params... params) { 
    try { 
     ... 
    } catch(SomeCustomException e) { 
     // If you need update UI, simply do this: 
     runOnUiThread(new Runnable() { 
     public void run() { 
      // update your UI component here. 
      myTextView.setText("Exception!!!"); 
     } 
     }); 
    } 
    return result; 
    } 

} 

希望這是有意義的。

4

更改的doInBackgroundObject返回類型以可能地傳遞一個Exception,然後使用instanceof()是代碼味道(不好的編程習慣)的源極。將返回類型限制爲想要返回的特定內容總是可取的。

基於此answer只需添加一個私人成員來存儲doInBackground中拋出的異常,然後在onPostExecute中檢查它的第一件事。

只有一個Exception需要被抓住,因爲你應該doInBackground停止行動後立即拋出異常,並妥善處理它onPostExecute,你必須訪問的UI元素,因此可以告知事故的用戶。

通用爲例(的AsyncTask的身體):

private Exception mException 

@Override 
protected Result doInBackground(Params... params) { 
    try { 
      // --- Do something --- // 
    } 
    catch(SomeException e){ mException = e; return null; } 
} 

@Override 
protected void onPostExecute(Result result) { 
    if (mException != null) { 
     // --- handle exception --- // 
     return; 
    } 

    // --- Perform normal post execution actions --- // 
}