usando una tiempo tarea studio que oncancelled implement hilos ejecutar doinbackground curso cierto cada asynctask android multithreading android-emulator android-asynctask

una - Android SDK AsyncTask doInBackground no se está ejecutando(subclase)



oncancelled asynctask android (9)

Android es Brutal! No puedo creer esto, qué implementación flakey cambia de día a hoy. Un día es un hilo único, el siguiente es 5 y el otro es 128.

De todos modos, aquí hay casi un reemplazo en reemplazo para el stock AsyncTask. Incluso puede llamarlo AsyncTask si así lo desea, pero para evitar confusiones se llama ThreadedAsyncTask. Debe ejecutar executeStart () en lugar de ejecutar porque execute () es final.

/** * @author Kevin Kowalewski * */ public abstract class ThreadedAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> { public AsyncTask<Params, Progress, Result> executeStart(Params... params){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ return executePostHoneycomb(params); }else{ return super.execute(params); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) private AsyncTask<Params, Progress, Result> executePostHoneycomb(Params... params){ return super.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); } }

Desde el 15/2/2012 todavía tengo que encontrar una buena explicación ni una razón por la cual esto no funcione. Lo más cercano a una solución es usar el enfoque Thread tradicional, pero ¿por qué incluir una clase que no funciona (aparentemente) en el SDK de Android?

Evenin ''SO!

Tengo una subclase AsyncTask:

// ParseListener had a callback which was called when an item was parsed in a // RSS-xml, but as stated further down it is not used at all right now. private class xmlAsync extends AsyncTask<String, RSSItem, Void> implements ParseListener

Eso se ejecuta así:

xmlAsync xmlThread = new xmlAsync(); xmlThread.execute("http://www.nothing.com");

Ahora esta subclase ha tenido un pequeño error. Anteriormente realizaba un análisis xml, pero cuando noté que no se llamaba doInBackground () , lo desgasté , línea por línea, y finalmente terminé con esto:

@Override protected Void doInBackground(String... params) { Log.v(TAG, "doInBackground"); return null; }

Que, por alguna razón, no registró nada. Sin embargo, agregué esto:

@Override protected void onPreExecute() { Log.v(TAG, "onPreExecute"); super.onPreExecute(); }

Y esa línea se registra cuando se ejecuta el hilo. Entonces de alguna manera se llama onPreExecute () pero no doInBackground () . Tengo otra AsyncTask ejecutándose en segundo plano al mismo tiempo, que funciona bien.

Actualmente estoy ejecutando la aplicación en un emulador, SDK Versión 15, Eclipse, Mac OS X 10.7.2, cerca del Polo Norte.

EDITAR:

@Override protected void onProgressUpdate(RSSItem... values) { if(values[0] == null) { // activity function which merely creates a dialog showInputError(); } else { Log.v(TAG, "adding "+values[0].toString()); _tableManager.addRSSItem(values[0]); } super.onProgressUpdate(values); }

_tableManager.addRSSItem () agrega más o menos una fila a SQLiteDatabase, inicializada con el contexto de la actividad. Se llama a publishProgress () mediante la devolución de llamada de Interface ParseListener. Sin embargo, dado que ni siquiera hago nada excepto log.v en doInBackground (), primero encontré esto innecesario para que aparezca.

EDICION 2:

Muy bien, solo para ser perfectamente claro, esta es la otra AsyncTask, ejecutándose en la misma actividad y funcionando perfectamente bien.

private class dbAsync extends AsyncTask<Void, RSSItem, Void> { Integer prevCount; boolean run; @Override protected void onPreExecute() { run = true; super.onPreExecute(); } @Override protected Void doInBackground(Void... params) { // TODO Auto-generated method stub run = true; prevCount = 0; while(run) { ArrayList<RSSItem> items = _tableManager.getAllItems(); if(items != null) { if(items.size() > prevCount) { Log.v("db Thread", "Found new item(s)!"); prevCount = items.size(); RSSItem[] itemsArray = new RSSItem[items.size()]; publishProgress(items.toArray(itemsArray)); } } SystemClock.sleep(5000); } return null; } @Override protected void onProgressUpdate(RSSItem... values) { ArrayList<RSSItem> list = new ArrayList<RSSItem>(); for(int i = 0; i < values.length; i++) { list.add(i, values[i]); } setItemsAndUpdateList(list); super.onProgressUpdate(values); } @Override protected void onCancelled() { run = false; super.onCancelled(); } }

EDIT 3:

Suspiro, lo siento, soy malo al hacer preguntas. Pero aquí está la inicialización de las Tareas.

xmlAsync _xmlParseThread; dbAsync _dbLookup; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); _dbLookup = new dbAsync(); _dbLookup.execute(); _xmlParseThread = new xmlAsync(); _xmlParseThread.execute("http://www.nothing.com", null); }


Basado en la respuesta de Matthieu, debajo de una clase de ayuda para ejecutar su AsyncTask correctamente dependiendo de la versión del SDK para evitar duplicar el código en su aplicación:

import android.annotation.SuppressLint; import android.os.AsyncTask; import android.os.Build; public class AsyncTaskExecutor<Params, Progress, Result> { @SuppressLint("NewApi") public AsyncTask<Params, Progress, Result> execute(final AsyncTask<Params, Progress, Result> asyncTask, final Params... params){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ return asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); } else{ return asyncTask.execute(params); } } }

Ejemplo de uso:

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

...

final MyTask myTask = new MyTask(); new AsyncTaskExecutor<Void, Void, List<String>>().execute(myTask);


Debe verificar esta respuesta: https://.com/a/10406894/347565 y el enlace a los grupos de google que incluye.

Tuve un problema similar al tuyo, todavía no estoy claro por qué no funciona, pero cambié mi código así y el problema desapareció:

ASyncTask<Void,Void,Void> my_task = new ASyncTask<Void,Void,Void>() { ... }; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) my_task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null); else my_task.execute((Void[])null);


La solución de Matthieu funcionará bien para la mayoría, pero algunos pueden enfrentar el problema; a menos que excave en muchos enlaces proporcionados aquí o desde la web, como la explicación de Anders Göransson . Estoy tratando de resumir algunas otras lecturas aquí y explicar rápidamente la solución si executeOnExecutor todavía está trabajando en un solo hilo ...

Comportamiento de AsyncTask().execute(); ha cambiado a través de las versiones de Android. Antes las tareas de Donut (Android: 1.6 API: 4) se ejecutaban en serie, desde Donut hasta Gingerbread (Android: 2.3 API: 9) tareas ejecutadas en paralelo; desde que la ejecución de Honeycomb (Android: 3.0 API: 11) fue cambiada a secuencial; sin embargo, se agregó un nuevo método AsyncTask().executeOnExecutor(Executor) para ejecución paralela.

En el procesamiento secuencial, todas las tareas de Async se ejecutan en un único subproceso y, por lo tanto, deben esperar antes de que finalice la tarea anterior. Si necesita ejecutar el código inmediatamente, necesita que las tareas se procesen en paralelo en hilos separados.

Con AsyncTask, la ejecución en serie no está disponible entre las versiones de Donut y Honeycomb, mientras que la ejecución en paralelo no está disponible antes de Donut.

Para el procesamiento paralelo después de Donut: compruebe la versión de compilación y, en función de ese uso, utilice el método .execute () o .executeOnExecutor (). El siguiente código puede ayudar ...

AsyncTask<Void,Void,Void> myTask = new AsyncTask<Void,Void,Void>() { ... }; // ... your AsyncTask code goes here if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else myTask.execute();

NOTE: función .executeOnExecutor() tiene comprobaciones si targetSdkVersion del proyecto es menor o igual que HONEYCOMB_MR1 (Android: 2.1 API: 7) y luego obliga al ejecutor a THREAD_POOL_EXECUTOR (que ejecuta las tareas secuencialmente en la publicación Honeycomb).
Si no ha definido una targetSdkVersion , se considera que minSdkVersion es la targetSdkVersion .
Por lo tanto, para ejecutar su AsyncTask en paralelo en la publicación Honeycomb, no puede dejar targetSdkVersion .


Puedes hacer esto de dos maneras:

Camino 1 :

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) // Above Api Level 13 { asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else // Below Api Level 13 { asyncTask.execute(); }

En caso de que la forma 1 no funcione para ti, prueba el modo 2 .

Camino 2

int mCorePoolSize = 60; int mMaximumPoolSize = 80; int mKeepAliveTime = 10; BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(mMaximumPoolSize); Executor mCustomThreadPoolExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.SECONDS, workQueue); asyncTask.executeOnExecutor(mCustomThreadPoolExecutor);

Espero que esto te ayudará.


Sé que esto puede ser muy tarde para el hilo, pero hay una razón por la que no funcionará en los emuladores posteriores de Android. Cuando se introdujo asynctask, Android solo permitía ejecutar uno a la vez, y luego, un poco después, no estoy seguro de qué versión, permitían ejecutar múltiples asynctasks a la vez, esto causaba problemas en muchas aplicaciones, y en Honeycomb + volvían a solo permitiendo que una asynctask se ejecute a la vez. A menos que cambie manualmente el grupo de subprocesos. Espero que aclare una o dos cosas para la gente.


Tuve el mismo problema: no puedo ejecutar una segunda AsyncTask después de llamar a "ejecutar" en una primera: doInBackground solo se llama para la primera.

Para responder por qué sucede esto, verifique esta answer (comportamiento diferente según el SDK)

Sin embargo, para su caso, este obstáculo se puede evitar utilizando executeOnExecutor (disponible a partir de 3.0 trabajado para mí usando 4.0.3), pero tenga cuidado con las limitaciones del tamaño del grupo de subprocesos y las colas.

¿Puedes probar algo como esto?

xmlAsync _xmlParseThread; dbAsync _dbLookup; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); _dbLookup = new dbAsync(); _dbLookup.execute(); _xmlParseThread = new xmlAsync(); _xmlParseThread.executeOnExecutor(_dbLookup.THREAD_POOL_EXECUTOR ,"http://www.nothing.com", null); }

Para su pregunta de actualización: se explica en los docs Básicamente solo para evitar todos los problemas que pueden provenir de multithreading como interferencia ...


Una cosa que me gustaría saber, y que realmente podría solucionar su problema, es ¿dónde está instanciando la instancia de su clase y llamando al método execute ()? Si lee la documentación de AsyncTask, ambas operaciones deben llevarse a cabo en la secuencia de interfaz de usuario principal. Si está creando su objeto y ejecutando ejecutar desde otro hilo, entonces onPreExecute podría disparar, no estoy 100% seguro aquí, pero el hilo de fondo no se creará ni se ejecutará.

Si está creando la instancia de su AsyncTask desde un hilo de fondo, o alguna otra operación que no tiene lugar en el hilo de la IU principal, podría considerar usar el método: Activity.runOnUiThread(Runnable)

Necesitará acceder a una instancia de su Actividad en ejecución para llamar a ese método, pero le permitirá ejecutar código en el subproceso UI desde algún otro código que no se esté ejecutando en el subproceso UI.

Espero que tenga sentido. Avíseme si puedo ayudar más.

David


creo que es el SDK. Tuve el mismo problema, y ​​después de cambiar el sdk objetivo de 15 a 11, todo funciona perfectamente.

con sdk15, aunque el AsyncTask.Status se está ejecutando, nunca se llama al doInBackground. Sin embargo, creo que tiene algo que ver con el hilo de la interfaz de usuario.