2012-06-08 11 views
8

Chcę złapać wyjątek wątku w doInBackground i wydrukować komunikat o błędzie w onPostExcecute. Problem polega na tym, że nie mam obiektu Throwable w onPostExecute. Jak do catch Wyjątek w wątku innym niż UI i wydrukować komunikat o błędzie w wątku UI?Catch Exception of AsyncTask. Potrzebujesz myślenia

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

    } 
} 

Aktualizacja po odebraniu Arun za:

To moja klasa AsyncTask wrapper. Ma zamiar obsługiwać Exception na doInBackground, ale nie mogę znaleźć dobrego rozwiązania, aby to zrobić.

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

można wdrożyć jakiś zestaw do wywołania zwrotne i się błąd. –

+0

Próbowałem, ale nie mogę zwrócić obu wyjątków i listy w doInBackground. Jak to zrobić? – Emerald214

+0

spróbuj zwrócić 'e.toString()' zamiast 'null' z' catch' z 'doInBackground()' ... – GAMA

Odpowiedz

7

Zmień typ powrotu doInBackground() do Object a gdy pojawi się wynik w onPostExecute(Object result) użyć operatora instanceOf aby sprawdzić, czy zwrócony wynik jest Exception lub List<String>.

Edit

Ponieważ wynik może być albo wyjątek lub inny właściwy Lista, można użyć następujących:

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

zmienić także następujące oświadczenie:

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

To jest dobre, ale nie rozwiązać problem, ponieważ nie można instancji sparametryzować typu (lista ). : [ – Emerald214

4

Wystarczy zapisać wyjątek na liście i obsłużyć go później, ponieważ funkcja onPostExecute() jest zawsze wywoływana za pomocą funkcji 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 
     ... 
    } 
    } 

} 

Jest to wykonalne, ale rzadko stosowane, ponieważ w większości sytuacji, chcemy obsłużyć wyjątek tak szybko, jak to trafiają i przechwycony:

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

} 

Nadzieja to sensu.

4

Zmiana typu zwracanej doInBackground do Object aby ewentualnie przekazać Exception a następnie użyć instanceof() jest źródłem zapachy kodu (złe praktyki programowania). Zawsze lepiej jest ograniczyć typ zwrotu do konkretnej rzeczy, którą chcesz zwrócić.

Na podstawie tego answer po prostu dodaj prywatnego członka do przechowywania wyjątku wyrzuconego w doInBackground, a następnie sprawdź go w pierwszej kolejności pod numerem onPostExecute.

Tylko jeden Exception musi być złapany, ponieważ należy zaprzestać działań w doInBackground natychmiast gdy jest wyjątek i obsługiwać go wdzięcznie w onPostExecute gdzie masz dostęp do elementów interfejsu użytkownika, a więc może informować użytkownika o nieszczęście.

Generic przykład (korpus 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 --- // 
}