para - manual de programacion android pdf
Ejecute AsyncTask varias veces (5)
En mi actividad utilizo una clase que se extiende desde AsyncTask y un parámetro que es una instancia de esa AsyncTask. Cuando llamo a mInstanceOfAT.execute("")
todo está bien. Pero la aplicación falla cuando presiono un botón de actualización que llama nuevamente a AsyncTask (en caso de que el trabajo de red no haya funcionado). Porque entonces aparece una excepción que dice
No se puede ejecutar la tarea: la tarea ya se ha ejecutado (una tarea se puede ejecutar solo una vez)
He intentado llamar a cancelar (verdadero) para la instancia de Asyctask, pero tampoco funciona. La única solución hasta ahora es crear nuevas instancias del Asyntask. ¿Es esa la forma correcta?
Gracias.
He hecho que mis tareas de rotación estén estáticas, lo que me ayudó a conectarlas, separarlas y volver a conectarlas a los subprocesos de la interfaz de usuario en los cambios de rotación. Pero para volver a su pregunta, lo que hago es crear una bandera para ver si el hilo se está ejecutando. Cuando quiera reiniciar el hilo, verifico si la tarea de rotación se está ejecutando si es que brindo una advertencia. Si no es así, lo hago nulo y luego creo uno nuevo, lo que funcionará alrededor del error que está viendo. Además, al completar con éxito anulo la tarea completa de rotación consciente para que esté lista para continuar.
Los motivos de las instancias de "apagar y olvidar" de ASyncTask se detallan bastante bien en la respuesta de Steve Prentice. Sin embargo, aunque se restringe la cantidad de veces que ejecuta un ASyncTask, puede hacer lo que quiera mientras se ejecuta el subproceso. .
Coloque 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 usted renuncia al uso de publishProgress () para el informe de progreso real. Pero si la memoria es su preocupación, este enfoque garantizará que solo una ASyncTask permanezca en el montón en tiempo de ejecución.
Sí, es cierto, el doc dice que solo se puede ejecutar un Asyntask.
Cada vez que necesite usarlo, tiene que instanciar:
// 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> {
}
Tuve el mismo problema. En mi caso, tengo una tarea que quiero hacer en onCreate()
y en onResume(
). Así que hice mi Asynctask estática y obtuve la instancia de ella. Ahora todavía tenemos el mismo problema.
Entonces, lo que hice en onPostExecute () es esto:
instance = null;
Teniendo en cuenta que verifico en el método estático getInstance que mi instancia no es nula, de lo contrario la creo:
if (instance == null){
instance = new Task();
}
return instance;
El método en postExecute vaciará la instancia y la volverá a crear. Por supuesto, esto se puede hacer fuera de la clase.
AsyncTask
instancias de AsyncTask
solo se pueden usar una vez.
En su lugar, simplemente llame a su tarea como new MyAsyncTask().execute("");
De los documentos de la API AsyncTask:
Enhebrar las reglas
Hay algunas reglas de enhebrado que se deben seguir para que esta clase funcione correctamente:
- La instancia de la tarea debe crearse en el hilo de la interfaz de usuario.
- execute (Params ...) debe invocarse en el subproceso UI.
- No invoque onPreExecute (), onPostExecute (Result), doInBackground (Params ...), onProgressUpdate (Progress ...) manualmente.
- La tarea se puede ejecutar solo una vez (se lanzará una excepción si se intenta una segunda ejecución).