Android llama a AsyncTask justo después de que otro termine
Tengo algún problema con Android AsyncTask. Hay una actividad que contiene algunos TextView un botón y una imagen. Cuando un usuario entró en esta actividad, inicie un asynctask para verificar si el usuario puede ir hacia la actividad (hasta que la tarea no termine el botón no activo). Entonces quiero comenzar otra asyntax para obtener la imagen. Así que hice una clase interna:
AsyncTask<String, Void, JSONObject>() authTask = new AsyncTask<String, Void, JSONObject>() { @Override protected JSONObject doInBackground(String... params) { //call the rest api } @Override protected void onPostExecute(JSONObject result) { // check the result // and make another asynctask AsyncTask<String, Void, Bitmap> imageTask = new Async.... { // get image } imageTask.execute(); } }
Y llamo authTask.execute();
Desde el subproceso de interfaz de usuario.
- Comportamiento de menú de opciones extraño en Android TabActivity
- Obtener No puede crear el controlador dentro de hilo que no ha llamado Looper.prepare () con código que funcionó para Android 4
- ¿Cómo puedo pasar un primitivo int a mi AsyncTask?
- Fragmentos de Android. Retener un AsyncTask durante la rotación de la pantalla o el cambio de configuración
- ListView onScroll añadir más elementos
Tengo un mal presentimiento acerca de esto, especialmente parece que no funciona (está bien pocas veces, pero de repente "congelar": no hay excepción sólo colgando y la barra de progreso está girando.No pasa nada y el botón no estará activo.) Hay otra manera de obtener una información y cuando se ha terminado inmediatamente iniciar otra tarea?
UDPATE: Trabajo con api nivel 10. En authTask consigo cierta información que es necesaria para iniciar imageTask (algunos id) así que tengo que llamar a estas tareas en una fila. En api nivel 10 es posible?
¡Gracias por adelantado!
Hermano Peter
- AsyncTask y Contextos
- Android AsyncTask dentro de AsyncTask
- ¿Cómo ejecutar algún código en el asíncrono de la interfaz de usuario de Android?
- Clase IntentService que no está ejecutando AsyncTask en el hilo principal de ui. Método de ejecución debe ser llamado desde el hilo principal, el hilo actualmente inferido es el trabajador
- ¿Por qué se ejecuta AsyncTask en el subproceso principal de una aplicación?
- AsyncTask - después de la ejecución, ¿cómo actualizar vista?
- Android Descargar varios archivos y mostrar el progreso en ListView
- Cómo detener asynctask hilo en Android?
Puede utilizar getStatus()
comprueba si el AsyncTask
está pendiente, en ejecución o terminado. Y cuando finsh inicie su nueva task.like:
if(authTask .getStatus() == AsyncTask.Status.PENDING){ // My AsyncTask has not started yet } if(authTask .getStatus() == AsyncTask.Status.RUNNING){ // My AsyncTask is currently doing work in doInBackground() } if(authTask .getStatus() == AsyncTask.Status.FINISHED){ // START NEW TASK HERE }
Ejemplo para tu aplicación:
btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (authTask != null && authTask.getStatus() == AsyncTask.Status.FINISHED) { //START YOUR NEW TASK HERE } else { //IGNORE BUTTON CLICK } } });
1
Usted podría escribir el código para authTask y luego para imageTask, uno tras otro, dentro de un solo doInBackground()
. Esta única instancia AsyncTask sería activada por una sola sentencia execute()
. Esto puede o no ser práctico dependiendo de las interacciones necesarias de la interfaz de usuario.
2
Editar: como se ha señalado por kabuku esta información es sobre todo para HoneyComb +. Pre HoneyComb Definitivamente iría con la opción 1 anterior. ExecuteOnExecutor () es api nivel 11+
En las versiones de receent, execute()
enviará sus AsyncTasks en serie por defecto (ICS +). Si desea asegurarse de que esto suceda, especifique el ejecutor en serie.
En su caso esto sería:
authTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); // Image task will only be done AFTER textViewTask is done imageTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
Y para las versiones más recientes un simple
... // ICS+ and pre honeycomb (I think) authTask.execute(); // Image task will only be done AFTER textViewTask is done imageTask.execute(); ...
Desde la documentación de AsycnTask.execute ():
Nota: esta función programa la tarea en una cola para un solo subproceso de fondo o grupo de subprocesos dependiendo de la versión de la plataforma. Cuando se introdujo por primera vez, AsyncTasks se ejecutaron en serie en un solo hilo de fondo. Comenzando con DONUT, esto fue cambiado a un grupo de hilos permitiendo que múltiples tareas funcionaran en paralelo. Después de HONEYCOMB, se planea cambiar esto de nuevo a un solo hilo para evitar errores comunes de aplicación causados por la ejecución paralela.
PS: Para ejecutar tareas independientes entre sí debe utilizar el AsyncTask.THREAD_POOL_EXECUTOR
. Eso requiere un ejecutor diferente:
// Go parallel! (NOT what you want) task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
No es un buen diseño para anidar AsyncTask. Hacer todo el trabajo pesado en doInBackground y simplemente publicar / actualizar los resultados. En otras palabras, combine el procesamiento de la segunda AsyncTask en su primera.
Desde el código que mostró que no parece tener sentido para generar segunda tarea. Sólo tienes que obtener la imagen dentro de doInBackground
de la primera tarea después de la autorización. Si necesita actualizar la interfaz de usuario, puede hacerlo en progreso.
int count; private void attemptConnect() { count = 0; str_lang = "English"; str_wait = "Plaese Wait"; new AllQuestion().execute(); } private class AllQuestion extends AsyncTask<String, String, String> { ProgressDialog pg; @Override protected void onPreExecute() { super.onPreExecute(); pg = new ProgressDialog(LanguageActivity.this); pg.setProgressStyle(ProgressDialog.STYLE_SPINNER); pg.setMessage(str_wait); pg.setCancelable(false); pg.show(); } @Override protected String doInBackground(String... strings) { try { SoapObject soapObject = new SoapObject(AppConstant.NAMESPACE, AppConstant.QUESTION_SOAP_METHOD); soapObject.addProperty("language", str_lang); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.dotNet = true; envelope.setOutputSoapObject(soapObject); HttpTransportSE se = new HttpTransportSE(AppConstant.webUrl); se.call(AppConstant.QUESTION_SOAP_ACTION, envelope); Object responce = envelope.getResponse(); Log.d("Question List:=>>", "" + responce); return responce.toString(); } catch (Exception e) { e.printStackTrace(); pg.dismiss(); return null; } } @Override protected void onPostExecute(String s) { super.onPostExecute(s); if (pg.isShowing()) { pg.dismiss(); Log.i(TAG, s); if (s != null || !s.equalsIgnoreCase("")) { try { JSONArray array = new JSONArray(s); for (int i = 0; i < array.length(); i++) { JSONObject obj = array.getJSONObject(i); String queId = obj.getString(TAG_QID); String que = obj.getString(TAG_QUE); String str_Opt = obj.getString(TAG_OPT); question = new Question(queId, que, str_lang, str_catId, str_Opt, manager.getDateTime()); helper.insertQuestion(question); } count++; if (count < 5) { if (count == 1) { str_lang = "German"; str_wait = "bitte warte einen Moment"; new AllQuestion().execute(); } if (count == 2) { str_lang = "Italian"; str_wait = "per favore aspetta un momento"; new AllQuestion().execute(); } if (count == 3) { str_lang = "Chinese"; str_wait = "请稍候"; new AllQuestion().execute(); } if (count == 4) { str_lang = "French"; str_wait = "patientez s'il-vous-plait"; new AllQuestion().execute(); } Log.d("All Question:-", question.toString()); } catch (JSONException e) { e.printStackTrace(); } } } } }
Tengo una idea para hacer series asíncronas en una sola tarea asíncrona :
protected Boolean doInBackground(String... params) { if(params[0] == "taskA") { //do somthing params[0] = "taskB"; } if(params[0] == "taskB") { //do somthing params[0] = "taskC"; } if(params[0] == "taskC") { //do somthing params[0] = "taskD"; } if(params[0] == "taskD") { //do somthing return true; }
Y en su hilo principal simplemente llame a una tarea asíncrona de la siguiente manera:
ShowMyProgress(); //if you like new MyAsyncTask().execute("taskA");
Y finalmente puede ocultar su progreso en onPostExecute como:
protected void onPostExecute(final Boolean success) { if (success) { .... HideMyProgress(); } }
- Los archivos Jar en la carpeta libs no se utilizan en la compilación de Android Gradle
- Cómo cambiar el tamaño de la pantalla física de Android desde el terminal / shell