2012-06-08 9 views
8

Quiero ver la excepción de un hilo en doInBackground e imprimir el mensaje de error en onPostExcecute. El problema es que no tengo el objeto Throwable en onPostExecute. Cómo captura Excepción en el subproceso sin interfaz de usuario y imprime el mensaje de error en UI-thread?Catch Exception of AsyncTask. Need Thinking

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

    } 
} 

Update después de la respuesta de Arun:

Ésta es mi clase AsyncTask envoltura. Tiene la intención de hacer Exception en doInBackground, pero no puedo encontrar una buena solución para hacerlo.

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

se puede aplicar algún tipo de devoluciones de llamada para establecer y obtener el error. –

+0

Lo intenté pero no puedo devolver Exception y List en doInBackground. ¿Cómo hacerlo? – Emerald214

+0

intente devolver 'e.toString()' en lugar de 'null' de' catch' of 'doInBackground()' ... – GAMA

Respuesta

7

Cambiar el tipo de retorno de doInBackground() a Object y cuando reciba el resultado en onPostExecute(Object result) utilizar el operador instanceOf para comprobar si el resultado devuelto es un Exception o la List<String>.

Editar

Puesto que el resultado puede ser o bien una excepción o de lo contrario la lista adecuada, se puede utilizar el siguiente:

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

también cambiar la siguiente declaración:

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

Esto está bien pero no lo hace resuelva el problema porque no puede instanciar el tipo parametrizado (Lista ). : [ – Emerald214

4

Simplemente almacene la excepción en una lista y trátela más tarde, ya que onPostExecute() siempre se llama después de 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 
     ... 
    } 
    } 

} 

Esto es factible, pero rara vez se utiliza, como en la mayor situación, queremos manejar la excepción tan pronto como son lanzados y apresado:

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

} 

Hope esto sentido.

4

Cambiar el tipo de retorno de doInBackground a Object para pasar, posiblemente, un Exception y luego usar instanceof() es una fuente de olor código (mala práctica de programación). Siempre es preferible restringir el tipo de devolución a lo específico que desea devolver.

Basado en este answer simplemente agregue un miembro privado para almacenar la excepción lanzada en doInBackground y luego verifique que lo primero en onPostExecute.

Sólo una Exception tiene por qué ser capturados porque se debe dejar las acciones en doInBackground de inmediato una vez que se produce la excepción y manejarla con gracia en onPostExecute donde se tiene acceso a los elementos de interfaz de usuario y así puede informar al usuario sobre el percance.

Ejemplo genérico (cuerpo de la 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 --- // 
}