Ejecutar AsyncTask varias veces

En mi actividad, utilizo una clase que se extiende desde AsyncTask y un parámetro que es una instancia de AsyncTask. Cuando llamo mInstanceOfAT.execute("") todo está bien. Pero la caída de la aplicación cuando presiono un botón de actualización que llama de nuevo el AsyncTask (En caso de que el trabajo de red no funcionó). Causa entonces aparece una excepción que dice

No se puede ejecutar la tarea: la tarea ya se ha ejecutado (una tarea sólo se puede ejecutar una vez)

He intentado llamar a cancel (true) para la instancia de Asyctask, pero tampoco funciona. La única solución hasta ahora es crear nuevas instancias de Asyntask. ¿Es esa la forma correcta?

Gracias.

AsyncTask instancias sólo se puede utilizar una vez.

En su lugar, sólo llame a su tarea como new MyAsyncTask().execute("");

Desde los Documentos de API de AsyncTask:

Reglas de segmentación

Hay algunas reglas de subprocesamiento que se deben seguir para que esta clase funcione correctamente:

  • La instancia de tarea debe crearse en el subproceso de la interfaz de usuario.
  • Execute (Params …) debe ser invocado en el subproceso de UI.
  • No llame a onPreExecute (), onPostExecute (Resultado), doInBackground (Params …), onProgressUpdate (Progreso …) manualmente.
  • La tarea se puede ejecutar sólo una vez (se producirá una excepción si se intenta una segunda ejecución).

Las razones de las instancias fire-and-forget de ASyncTask se detallan bastante bien en la respuesta de Steve Prentice. Sin embargo, mientras estás restringido en cuántas veces ejecutas un ASyncTask, eres libre de hacer lo que quieras mientras se está ejecutando el subproceso. .

Ponga su código ejecutable dentro de un bucle dentro de doInBackground () y use un bloqueo concurrente para activar cada ejecución. Puede recuperar los resultados utilizando publishProgress () / onProgressUpdate () .

Ejemplo:

 class GetDataFromServerTask extends AsyncTask<Input, Result, Void> { private final ReentrantLock lock = new ReentrantLock(); private final Condition tryAgain = lock.newCondition(); private volatile boolean finished = false; @Override protected Void doInBackground(Input... params) { lock.lockInterruptibly(); do { // This is the bulk of our task, request the data, and put in "result" Result result = .... // Return it to the activity thread using publishProgress() publishProgress(result); // At the end, we acquire a lock that will delay // the next execution until runAgain() is called.. tryAgain.await(); } while(!finished); lock.unlock(); } @Override protected void onProgressUpdate(Result... result) { // Treat this like onPostExecute(), do something with result // This is an example... if (result != whatWeWant && userWantsToTryAgain()) { runAgain(); } } public void runAgain() { // Call this to request data from the server again tryAgain.signal(); } public void terminateTask() { // The task will only finish when we call this method finished = true; lock.unlock(); } @Override protected void onCancelled() { // Make sure we clean up if the task is killed terminateTask(); } } 

Por supuesto, esto es un poco más complicado que el uso tradicional de ASyncTask, y renuncia al uso de publishProgress () para el informe de progreso real. Pero si la memoria es su preocupación, entonces este enfoque garantizará que sólo un ASyncTask permanezca en el montón en tiempo de ejecución.

He hecho mis tareas de rotación estática, que luego me ayudó a adjuntar, separar y volver a conectar a los hilos de la interfaz de usuario en los cambios de rotación. Pero para volver a tu pregunta, lo que hago es crear una bandera para ver si el hilo se está ejecutando. Cuando quiera reiniciar el hilo, comprobar si la tarea de rotación se está ejecutando si se trata de brindar una advertencia. Si no lo es, lo hago nulo y luego crear uno nuevo, que funcionará alrededor del error que está viendo. Además, al finalizar con éxito, anulo la tarea completada de rotación para que esté lista para ir de nuevo.

Tuve el mismo problema. En mi caso tengo una tarea que quiero hacer en onCreate() y en onResume( ). Así que hice mi Asynctask estático, y obtener la instancia de ella. Ahora tenemos el mismo problema.

Así que lo que hice en el onPostExecute () es esto:

 instance = null; 

Teniendo en cuenta que comprobar en el método estático getInstance que mi instancia no es nulo, de lo contrario lo creo:

 if (instance == null){ instance = new Task(); } return instance; 

El método en postExecute vaciará la instancia y lo recreará. Por supuesto esto se puede hacer fuera de la clase.

Sí, es cierto, el doc dice que sólo se puede ejecutar una Asyntask.

Cada vez que necesites usarlo tienes que instar:

 // Any time if you need to call her final FirmwareDownload fDownload = new FirmwareDownload(); fDownload.execute("your parameter"); static class FirmwareDownload extends AsyncTask<String, String, String> { } 
  • Descargar archivo como Android Market
  • Ejecución de Parallely de AsyncTask múltiple
  • AsyncTask devuelve la lista a la actividad
  • ListView es muy lento - android
  • Android AsyncTasks Cómo comprobar si la actividad aún se está ejecutando
  • Cómo mostrar brindis en AsyncTask en doInBackground
  • ¿Cómo manejar sin conexión a Internet y pérdida en Android?
  • Cómo pasar el resultado del método onpostexecute asynctask en la actividad principal android
  • Cómo agregar datos a BaseAdapter personalizado para listView - Android
  • ¿Cómo se ejecutan dos AsyncTasks en una actividad?
  • Barra de progreso de Android en ImageView
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.