Android: ¿Cómo actualizar una interfaz de usuario de AsyncTask si AsyncTask está en una clase aparte?

Odio la clase interior.

Tengo una actividad principal que lanza un AsyncTask de "vida corta".

AsyncTask está en un archivo independiente , no es una clase interna de la actividad principal

Necesito actualizaciones de tareas asíncronas un textView de la actividad principal.

Sé que puedo actualizar un TextView de onProgressUpdate, si AsyncTask es una clase interna

¿Pero cómo de una tarea externa, indipendiente, asíncrona?

UPDATE: Esto parece trabajar:

En acitivty llamo la tarea

backgroundTask = new BackgroundTask(this); backgroundTask.execute(); 

En el constructor he

 public BackgroundTask(Activity myContext) { debug = (TextView) myContext.findViewById(R.id.debugText); } 

Donde debug era un campo privado de AsyncTask.

Así que onProgressUpdate puedo

 debug.append(text); 

Gracias por todas las sugerencias

EDIT He editado la respuesta para usar WeakReference


AsyncTask siempre es una clase separada de Activity , pero sospecho que significa que está en un archivo diferente del archivo de clase de actividad, por lo que no puede beneficiarse de ser la clase interna de la actividad. Simplemente pase el contexto de la actividad como argumento a su tarea asíncrona (es decir, a su constructor)

 class MyAsyncTask extends AsyncTask<URL, Integer, Long> { WeakReference<Activity> mWeakActivity; public MyAsyncTask(Activity activity) { mWeakActivity = new WeakReference<Activity>(activity); } ... 

Y utilizar cuando lo necesite (recuerde no utilizar en durante doInBackground() ) es decir, cuando usted normalmente llamar

 int id = findViewById(...) 

En AsyncTask se llama ie

 Activity activity = mWeakActivity.get(); if (activity != null) { int id = activity.findViewById(...); } 

Tenga en cuenta que nuestra Activity puede desaparecer mientras doInBackground() está en progreso (por lo que la referencia devuelta puede convertirse en null ), pero usando WeakReference no WeakReference que WeakReference lo WeakReference (y pierda memoria) y como la Actividad se ha ido Incluso intentar actualizar el estado (aún, dependiendo de su lógica, puede que desee hacer algo como cambiar el estado interno o actualizar DB, pero debe tocarse la interfaz de usuario).

Uso de la interfaz 1) Crear una interfaz

 public interface OnDataSendToActivity { public void sendData(String str); } 

2) Lo implementa en su Actividad

 public class MainActivity extends Activity implements OnDataSendToActivity{ @Override protected void onCreate(Bundle savedInstanceState) { new AsyncTest(this).execute(new String[]{"AnyData"}); // start your task } @Override public void sendData(String str) { // TODO Auto-generated method stub } } 

3) Crear constructor en AsyncTask (Activity activity) {} Registre su interfaz en el archivo AsyncTask y el método de interfaz de llamada como se muestra a continuación.

 public class AsyncTest extends AsyncTask<String, Integer, String> { OnDataSendToActivity dataSendToActivity; public AsyncTest(Activity activity){ dataSendToActivity = (OnDataSendToActivity)activity; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); dataSendToActivity.sendData(result); } } 

Aquí, su OnPostExecute llamará después de toda la tarea realizada por AsyncTask y obtendrá "result" como un parámetro, devuelto por doInBackground () {return "";}.

Mientras que "dataSendToActivity.sendData (result)"; Llamará al método overrided de la actividad "public void sendData (String str) {}".

Un caso de borde a recordar: Asegúrese de pasar this , es decir, el contexto de la actividad actual a AsyncTask y no crear otra instancia de su actividad, de lo contrario su Activity será destruida y se creará una nueva.

Simplemente pasa el contexto (actividad o lo que sea) a tu AsyncTask en un constructor y luego en onSuccess o onProgressUpdate llama lo que necesites en el contexto.

Escribí una pequeña extensión de AsyncTask para este tipo de escenario. Le permite mantener su AsyncTask en una clase aparte, pero también le da un acceso conveniente a la finalización de las Tareas:

 public abstract class ListenableAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result>{ @Override protected final void onPostExecute(Result result) { notifyListenerOnPostExecute(result); } private AsyncTaskListener<Result> mListener; public interface AsyncTaskListener<Result>{ public void onPostExecute(Result result); } public void listenWith(AsyncTaskListener<Result> l){ mListener = l; } private void notifyListenerOnPostExecute(Result result){ if(mListener != null) mListener.onPostExecute(result); } } 

Así que primero se extiende ListenableAsyncTask en lugar de AsyncTask. A continuación, en su código UI, hacer una instancia concreta y set listenWith (…).

Haga una función estática en su clase de actividad pasando el contexto en ella para actualizar su vista de texto y luego llamar a esta función en su clase AsynkTask para actualizar.

En clase de actividad: public static void updateTextView () {

// tu código aquí}

En clase AynckTask llame a esta función.

La Cuestión ya ha sido contestada, todavía estoy publicando cómo debería ser hecho supongo ..

Clase de Mainactivity

  public class MainActivity extends Activity implements OnClickListener { TextView Ctemp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Ctemp = (TextView) findViewById(R.id.Ctemp); doConv = (Button) findViewById(R.id.doConv); doConv.setOnClickListener(this); } @Override public void onClick(View arg0) // The conversion to do { new asyncConvert(this).execute(); } } 

Ahora en la clase asíncrona

 public class asyncConvert extends AsyncTask<Void, Void, String> { SoapPrimitive response = null; Context context; public asyncConvert(Context callerclass) { contextGUI = callerclass; } . . . . protected void onPostExecute(String result) { ((MainActivity) contextGUI).Ctemp.setText(result); // changing TextView } } 
  /** * Background Async Task to Load all product by making HTTP Request * */ public static class updateTExtviewAsyncTask extends AsyncTask<String, String, String> { Context context; ProgressDialog pDialog; String id, name; String state_id; //--- Constructor for getting network id from asking method public updateTExtviewAsyncTask(Context context,String id,String city) { context = context; state_id = id; city_name = city; } /* * * Before starting background thread Show Progress Dialog * */ @Override protected void onPreExecute() { super.onPreExecute(); pDialog = ProgressDialog.show(context, "","Please wait...", true, true); pDialog.show(); } /** * getting All products from url * */ protected String doInBackground(String... args) { return null; } /** * After completing background task Dismiss the progress dialog * **/ protected void onPostExecute(String file_url) { YourClass.UpdateTextViewData("Textview data"); } } 

// colocar este código dentro de su clase de actividad y también declarar la actualización textview static

  public static void UpdateTextViewData(String tvData) { tv.setText(tvData); } 
  • Las imágenes (base64) no se suben correctamente
  • AndroidRX - ejecuta el método en segundo plano
  • ¿Cómo puedo reutilizar una clase interna en Java / Android?
  • utilizar AsyncTask para mostrar datos en ListView
  • Android SQLite Query, insertar, actualizar, eliminar, siempre tiene que estar en el hilo de fondo?
  • ProgressDialog no funciona en AsyncTask externo
  • ¿Por qué no AsyncTasks siempre funcionan dentro de un onClickListener?
  • Espere a que se complete el AsyncTask múltiple
  • Comprobación del estado de AsyncTask de otra actividad
  • ¿Cómo puedo ejecutar esta clase en el hilo de interfaz de usuario?
  • ¿Qué sucede en Activity.finish () con AsyncTask todavía en ejecución en segundo plano?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.