La mejor manera de administrar el ProgressDialog de AsyncTask

Me gustaría usar el AsyncTask para gestionar algunos lógica de negocio en mi aplicación. ¿Cuál es el mejor patrón para usar el onProgressUpdate(...) de AsyncTask definido en archivos separados (no como clase innter de Activity ) Tengo dos ideas:
1. La forma más sencilla: crear ProgressDialog en Activity (usando el onCreateDialog(...) ) y pasar referencia a mi subclase de AsyncTask por constructor (override onProgressUpdate(...) dentro de mi subclase AsyncTask ). La desventaja de esta solución es el uso de componentes de interfaz de usuario dentro del código de la lógica de negocio.

FooTask1.java:

 public class FooTask1 extends AsyncTask<Void, Integer, Void> { private ProgressDialog mProgressDialog; public FooTask1(ProgressDialog progressDialog) { super(); mProgressDialog = progressDialog; } @Override protected Void doInBackground(Void... unused) { // time consuming operation for (int i=0; i<=100; i++) { this.publishProgress(i); try { Thread.sleep(100); } catch (Exception e) {} } return null; } @Override protected void onProgressUpdate(Integer... progress) { mProgressDialog.setProgress(progress[0]); } @Override protected void onPostExecute(Void result) { mProgressDialog.dismiss(); } } 

FooActivity1.java:

 public class FooActivity1 extends Activity { private static final int DIALOG_PROGRESS_ID = 0; private ProgressDialog mProgressDialog; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); showDialog(DIALOG_PROGRESS_ID); new FooTask(mProgressDialog).execute(); } @Override protected Dialog onCreateDialog(int id) { switch(id) { case DIALOG_PROGRESS_ID: mProgressDialog = new ProgressDialog(this); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.setMessage("Loading..."); mProgressDialog.setCancelable(false); return mProgressDialog; default: return null; } } } 

2.El modo más sofisticado: anula el onProgressUpdate(...) de AsyncTask dentro de la clase Activity :

FooTask2.java:

 public class FooTask2 extends AsyncTask<Void, Integer, Void> { @Override protected Void doInBackground(Void... unused) { // time consuming operation for (int i=0; i<=100; i++) { this.publishProgress(i); try { Thread.sleep(100); } catch (Exception e) {} } return null; } } 

FooActivity2.java

 public class FooActivity2 extends Activity { private static final int DIALOG_PROGRESS_ID = 0; private ProgressDialog mProgressDialog; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); showDialog(DIALOG_PROGRESS_ID); new FooTaskLoader().execute(); } @Override protected Dialog onCreateDialog(int id) { switch(id) { case DIALOG_PROGRESS_ID: mProgressDialog = new ProgressDialog(this); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.setMessage("Loading..."); mProgressDialog.setCancelable(false); return mProgressDialog; default: return null; } } private class FooTaskLoader extends FooTask2 { @Override protected void onProgressUpdate(Integer... progress) { mProgressDialog.setProgress(progress[0]); } @Override protected void onPostExecute(Void result) { dismissDialog(DIALOG_PROGRESS_ID); } } } 

Preferiría aislar las cosas de AsyncTask que aislar AsyncTask de Activity.

En general, AsyncTask tiene un diseño muy específico y el caso de uso en el ciclo de vida de la aplicación Android, es decir, ejecutar una tarea de tiempo en el hilo de fondo, una vez hecho, actualizar la vista de la actividad en el hilo de la interfaz de usuario. Por eso siempre se recomienda usarla como una clase interna de Actividad.

Un diseño más OO IMO está aislando y centralizando su lógica de negocio en un POJO (para la reutilización). Para ver si hay testabilidad, puedes hacer algo como esto:
1. Definir una interfaz IBusinessDAO
2. Definir RealBusinessDAO implementa IBusinessDAO
3. Definir MockBusinessDAO implementa IBusinessDAO
4. Llame a IBusinessDAO.foo (); Dentro de AsyncTask.doInBackground ()

Para la unidad de prueba de su lógica de negocio, ya que es un POJO, puede utilizar puramente JUnit escribir su caso de prueba. A veces queremos probar el componente de interfaz de usuario y no nos importa cómo se implementa la lógica de negocio subyacente, por ejemplo, mi lógica de negocios se conecta al servidor http remoto descargar algunos datos json, no quiero hacerlo cada vez que sólo Quiero probar el diseño de interfaz de usuario, para esta situación, puedo cambiar fácilmente mi uso de la actividad MockBusinessDAO (tipo de concepto DI de primavera) de esta manera:

 public class MyActivity extends Activity { IBusinessDAO businessDAO; ... ... private class MyAsyncTask extends AsyncTask<Void, Void, Void> { ... ... protected void doInBackground(Void... params) { businessDAO.foo(); } } ... ... public void onCreate(Bundle savedInstanceState) { if (runInTest) businessDAO = new MockBusinessDAO(); else businessDAO = new RealBusinessDAO(); new myAsyncTask().execute(); } } 

Algunas ventajas de hacer esto son:
1. La implementación de AsyncTask es fácil y limpia (varias líneas de código en doInBacnground ())
2. Implementación de la lógica de negocio es puramente POJO, mejorar la reutilización.
3. La lógica de negocio de la prueba del aislamiento y el componente de la interfaz de usuario, mejoran la testabilidad.

Espero que la ayuda.

  1. Solución número uno es probablemente la forma en que yo lo manejar – Esa es la forma de la estructura de Android. Un giro a esta solución (y probablemente como lo manejaría, si el AsyncTask no podría encajar en la clase de Activity ) pasaría un Context como el parámetro en su lugar, y luego instanciar y mostrar el ProgressDialog en onPreExecute .

  2. Solución número 2 es básicamente lo mismo que crear el diálogo como una clase interna – por lo que también podría hacer que si vas para este.

  • Patrón de diseño de Android MVVM
  • Buenas prácticas: Patrón de diseño para la navegación en pantalla 2D HUD
  • Utilizar try / catch para evitar que la aplicación se bloquee
  • Proyecto de la Biblioteca de Android - Definición de clases
  • Patrón MVC en Android
  • Patrón para reutilizar Android AsnycTask sobre varias actividades?
  • Patrón de Android AsyncTask / doInBackground
  • Buenos patrones de diseño para codificar muchas solicitudes HTTP en Android
  • ¿Cuál es el principio del patrón de diseño en el desarrollo de Android?
  • ContentProvider con varias tablas
  • Mejores prácticas para "capa de datos" en las aplicaciones para clientes de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.