Ejemplo AsyncTask Android

Estaba leyendo sobre AsyncTask , y probé el sencillo progtwig a continuación. pero no parece funcionar. ¿Cómo puedo hacer que funcione?

 package com.test; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.provider.Settings.System; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.view.View.OnClickListener; public class AsyncTaskActivity extends Activity { Button btn; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button1); btn.setOnClickListener((OnClickListener) this); } public void onClick(View view){ new LongOperation().execute(""); } private class LongOperation extends AsyncTask { @Override protected String doInBackground(String... params) { for(int i=0;i<5;i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); return null; } @Override protected void onPostExecute(String result) { } @Override protected void onPreExecute() { } @Override protected void onProgressUpdate(Void... values) { } } } 

Solo bash cambiar la etiqueta después de 5 segundos en el proceso de fondo.

Este es mi main.xml :

        

Está bien, está intentando acceder a la GUI a través de otro hilo. Esto, en general, no es una buena práctica.

El AsyncTask ejecuta todo en doInBackground() dentro de otro subproceso, que no tiene acceso a la GUI donde están sus vistas.

preExecute() y postExecute() ofrecen acceso a la GUI antes y después de que se produzca el levantamiento pesado en este nuevo hilo, incluso puede pasar el resultado de la operación larga a postExecute() para mostrar los resultados del procesamiento.

Vea estas líneas donde luego estará actualizando su TextView:

 TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); 

ponerlos en PostExecute()

Luego verás tu texto de TextView actualizado después de completar doInBackground .

EDITAR: Me di cuenta de que su oyente onClick no comprueba para ver qué vista se ha seleccionado. Encuentro que la forma más fácil de hacer esto es a través de declaraciones de cambio. Tengo una clase completa editada a continuación con todas las sugerencias para evitar confusiones.

 import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.provider.Settings.System; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.view.View.OnClickListener; public class AsyncTaskActivity extends Activity implements OnClickListener { Button btn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button1); // because we implement OnClickListener we only have to pass "this" // (much easier) btn.setOnClickListener(this); } public void onClick(View view) { // detect the view that was "clicked" switch (view.getId()) { case R.id.button1: new LongOperation().execute(""); break; } } private class LongOperation extends AsyncTask { @Override protected String doInBackground(String... params) { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.interrupted(); } } return "Executed"; } @Override protected void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); // txt.setText(result); // might want to change "executed" for the returned string passed // into onPostExecute() but that is upto you } @Override protected void onPreExecute() {} @Override protected void onProgressUpdate(Void... values) {} } } 

Mi respuesta completa está aquí , pero aquí hay una imagen explicativa para complementar las otras respuestas en esta página. Para mí, entender dónde estaban todas las variables era la parte más confusa al principio.

enter image description here

Estoy seguro de que se está ejecutando correctamente, pero estás tratando de cambiar los elementos de la interfaz de usuario en el hilo de fondo y eso no funcionará.

Revisa tu llamada y AsyncTask de la siguiente manera:

Clase de llamada

Nota: personalmente sugiero usar onPostExecute() siempre que ejecute su subproceso AsyncTask y no en la clase que extiende AsyncTask. Creo que hace que el código sea más fácil de leer, especialmente si necesita AsyncTask en múltiples lugares manejando los resultados ligeramente diferente.

 new LongThread() { @Override public void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.output); txt.setText(result); } }.execute(""); 

Clase LongThread (extiende AsyncTask):

 @Override protected String doInBackground(String... params) { for(int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } return "Executed"; } 

Concepto y código aquí

He creado un ejemplo simple para usar AsyncTask de Android. Comienza con onPreExecute(), doInBackground(), publishProgress() y finalmente onProgressUpdate() .

En este doInBackground () funciona como un hilo de fondo, mientras que otros funciona en el subproceso UI. No puede acceder a un elemento de IU en doInBackground (). La secuencia es la misma que he mencionado.

Sin embargo, si necesita actualizar cualquier widget desde doInBackground , puede publishProgress desde doInBackground que llamará a onProgressUpdate update para actualizar su widget de interfaz de usuario.

 class TestAsync extends AsyncTask { String TAG = getClass().getSimpleName(); protected void onPreExecute (){ super.onPreExecute(); Log.d(TAG + " PreExceute","On pre Exceute......"); } protected String doInBackground(Void...arg0) { Log.d(TAG + " DoINBackGround","On doInBackground..."); for(int i=0; i<10; i++){ Integer in = new Integer(i); publishProgress(i); } return "You are at PostExecute"; } protected void onProgressUpdate(Integer...a){ super.onProgressUpdate(a); Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]); } protected void onPostExecute(String result) { super.onPostExecute(result); Log.d(TAG + " onPostExecute", "" + result); } } 

Llámalo así en tu actividad:

 new TestAsync().execute(); 

Referencia del desarrollador aquí

Mueva estas dos líneas:

 TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); 

de su método doInBackground de doInBackground y ponerlos en el método onPostExecute . Su AsyncTask debería verse más o menos así:

 private class LongOperation extends AsyncTask { @Override protected String doInBackground(String... params) { try { Thread.sleep(5000); // no need for a loop } catch (InterruptedException e) { Log.e("LongOperation", "Interrupted", e); return "Interrupted"; } return "Executed"; } @Override protected void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.output); txt.setText(result); } } 

El ejemplo más corto para simplemente hacer algo de forma asíncrona:

 class MyAsyncTask extends android.os.AsyncTask { @Override protected Object doInBackground(Object[] objects) { //do something asynchronously return null; } } 

Para ejecutarlo:

 (new MyAsyncTask()).execute(); 

Cuando se ejecuta una tarea asíncrona, la tarea pasa por 4 pasos:

  1. onPreExecute ()
  2. doInBackground (Params …)
  3. onProgressUpdate (Progreso …)
  4. onPostExecute (Resultado)

A continuación se muestra un ejemplo de demostración

 private class DownloadFilesTask extends AsyncTask { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } } 

y una vez que creó, una tarea se ejecuta de manera muy simple:

  new DownloadFilesTask().execute(url1, url2, url3); 

Espero que esto ayude...

Antecedentes / Teoría

AsyncTask le permite ejecutar una tarea en una cadena de fondo, mientras publica resultados en la secuencia de la interfaz de usuario.

El usuario siempre debe poder interactuar con la aplicación, por lo que es importante evitar el locking del hilo principal (UI) con tareas como descargar contenido de la web.

Es por eso que usamos una AsyncTask .

Ofrece una interfaz sencilla envolviendo la cola de mensajes de la interfaz de usuario y el manejador que le permiten enviar y procesar objetos y mensajes ejecutables de otros hilos .

Implementación

AsyncTask es una clase genérica. (Toma tipos parametrizados en su constructor)

Utiliza estos tres tipos generics:

Params : el tipo de parámetros enviados a la tarea en la ejecución.

Progress : el tipo de unidades de progreso publicadas durante el cálculo de fondo.

Result : el tipo de resultado del cálculo de fondo.

No todos los tipos son siempre utilizados por una tarea asincrónica. Para marcar un tipo como no utilizado, simplemente use el tipo Void:

private class MyTask extends AsyncTask { ... }

Estos tres parámetros corresponden a tres funciones principales que puede anular en AsyncTask :

  • doInBackground(Params...)
  • onProgressUpdate(Progress...)
  • onPostExecute(Result)

Para ejecutar AsyncTask

call execute() con los parámetros que se enviarán a la tarea de fondo.

Lo que pasa

  1. En el hilo principal / IU, se llama a onPreExecute() . (Para inicializar algo en este hilo, como mostrar una barra de progreso en la interfaz de usuario).

  2. En un hilo de fondo, se doInBackground(Params...) . (Los parámetros son los que pasan a la función Ejecutar).

    • Donde debe pasar la tarea de larga duración

    • Debe anular al menos doInBackground() para usar AsyncTask.

    • Llame a publishProgress(Progress...) para actualizar una pantalla de progreso en la interfaz de usuario mientras el cálculo en segundo plano todavía se está ejecutando. (por ejemplo, animar una barra de progreso o mostrar registros en un campo de texto).

      • Esto hace que onProgressUpdate() sea ​​llamado.
  3. En el hilo de fondo, se devuelve un resultado de doInBackground() . Esto desencadena el siguiente paso.

  4. En el hilo principal / IU, onPostExecute() llamado con el resultado devuelto.

Ejemplos

Usando de nuevo el ejemplo de la tarea de locking para descargar algo de la web,

  • El Ejemplo A descarga una imagen y la muestra en un ImageView,
  • mientras que el Ejemplo B descarga algunos archivos .

Ejemplo A

El método doInBackground() descarga la imagen y la almacena en un objeto de tipo BitMap. El método onPostExecute() toma el bitmap y lo coloca en ImageView.

 class DownloadImageTask extends AsyncTask { ImageView bitImage; public DownloadImageTask(ImageView bitImage) { this.bitImage = bitImage; } protected Bitmap doInBackground(String... urls) { String urldisplay = urls[0]; Bitmap mBmp = null; try { InputStream in = new java.net.URL(urldisplay).openStream(); mBmp = BitmapFactory.decodeStream(in); } catch (Exception e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } return mBmp; } protected void onPostExecute(Bitmap result) { bitImage.setImageBitmap(result); } } 

Ejemplo B

  private class DownloadFilesTask extends AsyncTask { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } } 

Ejemplo B ejecución

 new DownloadFilesTask().execute(url1, url2, url3); 

Cuando está en el hilo de trabajo, no puede manipular directamente elementos de IU en Android.

Cuando usa AsyncTask, comprenda los métodos de callback.

Por ejemplo:

 public class MyAyncTask extends AsyncTask{ @Override protected void onPreExecute() { // Here you can show progress bar or something on the similar lines. // Since you are in a UI thread here. super.onPreExecute(); } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); // After completing execution of given task, control will return here. // Hence if you want to populate UI elements with fetched data, do it here. } @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values); // You can track you progress update here } @Override protected Void doInBackground(Void... params) { // Here you are in the worker thread and you are not allowed to access UI thread from here. // Here you can perform network operations or any heavy operations you want. return null; } } 

FYI: para acceder al hilo de UI desde un hilo de trabajo, o bien utiliza el método runOnUiThread () o el método de publicación en su vista.

Por ejemplo:

 runOnUiThread(new Runnable() { textView.setText("something."); }); or yourview.post(new Runnable() { yourview.setText("something"); }); 

Esto te ayudará a conocer las cosas mejor. Por lo tanto, en su caso, debe configurar su vista de texto en el método onPostExecute ().

Recomendaría hacerte la vida más fácil usando esta biblioteca para trabajos de fondo https://github.com/Arasthel/AsyncJobLibrary

Es así de simple …

 AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() { @Override public void doOnBackground() { startRecording(); } }); 

Tarea de Async de muestra con solicitud POST:

 List params = new ArrayList(); params.add(new BasicNameValuePair("key1", "value1")); params.add(new BasicNameValuePair("key1", "value2")); new WEBSERVICEREQUESTOR(URL, params).execute(); class WEBSERVICEREQUESTOR extends AsyncTask { String URL; List parameters; private ProgressDialog pDialog; public WEBSERVICEREQUESTOR(String url, List params) { this.URL = url; this.parameters = params; } @Override protected void onPreExecute() { pDialog = new ProgressDialog(LoginActivity.this); pDialog.setMessage("Processing Request..."); pDialog.setIndeterminate(false); pDialog.setCancelable(false); pDialog.show(); super.onPreExecute(); } @Override protected String doInBackground(String... params) { try { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpEntity httpEntity = null; HttpResponse httpResponse = null; HttpPost httpPost = new HttpPost(URL); if (parameters != null) { httpPost.setEntity(new UrlEncodedFormEntity(parameters)); } httpResponse = httpClient.execute(httpPost); httpEntity = httpResponse.getEntity(); return EntityUtils.toString(httpEntity); } catch (Exception e) { } return ""; } @Override protected void onPostExecute(String result) { pDialog.dismiss(); try { } catch (Exception e) { } super.onPostExecute(result); } } 

Debe declarar el botón onclicklistener, una vez que haga clic en él llama a la clase AsyncTask DownloadJson, el proceso se mostrará a continuación:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button1); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new DownloadJson().execute(); } }); } 

  // DownloadJSON AsyncTask private class DownloadJson extends AsyncTask { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Void doInBackground(Void... params) { newlist = new ArrayList>(); json = jsonParser.makeHttpRequest(json, "POST"); try { newarray = new JSONArray(json); for (int i = 0; i < countdisplay; i++) { HashMap eachnew = new HashMap(); newobject = newarray.getJSONObject(i); eachnew.put("id", newobject.getString("ID")); eachnew.put("name", newobject.getString("Name")); newlist.add(eachnew); } } } catch (JSONException e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void args) { newlisttemp.addAll(newlist); NewAdapterpager newadapterpager = new NewAdapterpager(ProcesssActivitypager.this,newlisttemp); newpager.setAdapter(newadapterpager); } } 
  private class AsyncTaskDemo extends AsyncTask { @Override protected void onPreExecute() { super.onPreExecute(); // Showing progress dialog progressDialog = new ProgressDialog(this); progressDialog.setMessage("Loading..."); progressDialog.setCancelable(false); progressDialog.show(); } @Override protected Void doInBackground(Void... arg0) { //do code here return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); // Dismiss the progress dialog if (progressDialog.isShowing()) { progressDialog.dismiss(); } } @Override protected void onCancelled() { super.onCancelled(); progressDialog.dismiss(); Toast toast = Toast.makeText(getActivity(), "Error is occured due to some probelm", Toast.LENGTH_LONG); toast.setGravity(Gravity.TOP, 25, 400); toast.show(); } } 

Simplemente:

 LongOperation MyTask = new LongOperation(); MyTask.execute(); 

Cambie su código como se indica a continuación:

 @Override protected void onPostExecute(String result) { runOnUiThread(new Runnable() { public void run() { TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); } }); }