uso studio oncancelled implement hilos ejemplos curso asynctask android android-asynctask

studio - implement asynctask android



Ejemplo de AsyncTask para Android (15)

Estaba leyendo sobre AsyncTask , y probé el sencillo programa 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<String, Void, String> { @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 intento cambiar la etiqueta después de 5 segundos en el proceso de fondo.

Este es mi main.xml :

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:indeterminate="false" android:max="10" android:padding="10dip"> </ProgressBar> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Start Progress" > </Button> <TextView android:id="@+id/output" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Replace"/> </LinearLayout>


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 subproceso en segundo plano, mientras que otro trabaja en el subproceso de la interfaz de usuario. No puede acceder a un elemento UI en doInBackground (). La secuencia es la misma que he mencionado.

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

class TestAsync extends AsyncTask<Void, Integer, String> { 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í


Antecedentes / Teoría

AsyncTask le permite ejecutar una tarea en un subproceso en segundo plano, mientras publica los resultados en el subproceso de la interfaz de usuario.

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

Es por eso que usamos una AsyncTask .

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

Implementación

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

Utiliza estos tres tipos genéricos:

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

Progress : el tipo de unidades de progreso publicadas durante el cálculo en segundo plano.

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

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

private class MyTask extends AsyncTask<Void, Void, Void> { ... }

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

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

Para ejecutar AsyncTask

llame a execute() con los parámetros que se enviarán a la tarea en segundo plano.

Lo que pasa

  1. En el hilo principal / UI, 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 se pasan a la función Ejecutar).

    • Donde debería suceder 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 de fondo todavía se está ejecutando. (por ejemplo, animar una barra de progreso o mostrar registros en un campo de texto).

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

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

Ejemplos

Usando nuevamente el ejemplo de la tarea de bloqueo es 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 mapa de bits y lo coloca en el ImageView.

class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 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<URL, Integer, Long> { 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"); } }

Ejecución del ejemplo B

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


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"); } }); }


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

Cuando esté utilizando AsyncTask, comprenda los métodos de devolución de llamada.

Por ejemplo:

public class MyAyncTask extends AsyncTask<Void, Void, Void>{ @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; } }

Para su información: para acceder al subproceso de la interfaz de usuario desde un subproceso de trabajo, puede utilizar 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 mejor las cosas. Por lo tanto, en su caso, debe configurar su vista de texto en el método onPostExecute ().


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

  1. onPreExecute ()
  2. DoInBackground (Parámetros ...)
  3. onProgressUpdate (Progreso ...)
  4. onPostExecute (Resultado)

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

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { 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 creaste, una tarea se ejecuta muy simplemente:

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

Espero que esto ayude...


Debe declarar el botón onclicklistener; una vez que haga clic en él, se llama AsyncTask class 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<Void, Void, Void> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Void doInBackground(Void... params) { newlist = new ArrayList<HashMap<String, String>>(); json = jsonParser.makeHttpRequest(json, "POST"); try { newarray = new JSONArray(json); for (int i = 0; i < countdisplay; i++) { HashMap<String, String> eachnew = new HashMap<String, String>(); 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); } }


Ejemplo de tarea asíncrona con solicitud POST:

List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("key1", "value1")); params.add(new BasicNameValuePair("key1", "value2")); new WEBSERVICEREQUESTOR(URL, params).execute(); class WEBSERVICEREQUESTOR extends AsyncTask<String, Integer, String> { String URL; List<NameValuePair> parameters; private ProgressDialog pDialog; public WEBSERVICEREQUESTOR(String url, List<NameValuePair> 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); } }


El ejemplo más corto para hacer algo asíncrono:

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

Para ejecutarlo:

(new MyAsyncTask()).execute();


Estoy seguro de que se está ejecutando correctamente, pero está intentando cambiar los elementos de la IU 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() dondequiera que ejecute su subproceso de AsyncTask y no en la clase que extiende el mismo AsyncTask. Creo que hace que el código sea más fácil de leer, especialmente si necesita la AsyncTask en varios lugares que manejan los resultados ligeramente diferentes.

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"; }


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


Mueve estas dos líneas:

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

fuera del método doInBackground de su AsyncTask y doInBackground en el método onPostExecute . Tu AsyncTask debería verse así:

private class LongOperation extends AsyncTask<String, Void, String> { @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); } }


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

AsyncTask ejecuta todo en doInBackground() dentro de otro hilo, 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 postExecute() el trabajo pesado en este nuevo hilo, incluso puede pasar el resultado de la operación larga a postExecute() para luego mostrar los resultados del procesamiento.

Vea estas líneas donde más adelante está actualizando su TextView:

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

PostExecute() en PostExecute()

Luego, verás que tu texto de TextView se actualiza después de que se completa doInBackground .

EDITAR: Noté que su oyente onClick no comprueba qué Vista ha sido seleccionada. Encuentro que la forma más fácil de hacer esto es a través de instrucciones 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<String, Void, String> { @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) {} } }


Recomendaría hacer su vida más fácil usando esta biblioteca para trabajos en segundo plano https://github.com/Arasthel/AsyncJobLibrary

es este simple ..

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


Simplemente:

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


private class AsyncTaskDemo extends AsyncTask<Void, Void, Void> { @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(); } }