¿Cómo se puede utilizar una interfaz para diferentes tareas de fondo de Android?

Bueno, tengo una clase de actividad con dos tareas en segundo plano (Async-Task) que se han definido en dos clases separadas como

public class GettingBeaconsList extends AsyncTask public class GettingAirports extends AsyncTask 

que se inicializan y ejecutan en MainClass

 public class MainClass extends Activity implements DelegateTaskCompleted { int ServiceBoolean = 0; public OnClickListener LoadingBeaconList = new OnClickListener() { public void onClick(View v) { ServiceBoolean =1; new GettingBeaconsList (context,MainClass.this).execute(); } } public OnClickListener LoadingAirportList= new OnClickListener() { public void onClick(View v) { ServiceBoolean =2; new GettingAirports(context,MainClass.this).execute(); } } @Override public void JsonArrayLoaded(JSONArray result) { // bla bla or whatever here i write, does not matter if(ServiceBoolean == 1) { // Load activity 5 } else if( ServiceBoolean == 2) { // Load activity 6 } else if( ServiceBoolean==3 ) { // display Toast or Alert Box or load Activity number 8 } } } 

Ahora en el código anterior MainClass.this se almacena como referencia de interfaz en SubClasses AsynTask como este

 private Context context = null; private DelegateTaskCompleted delegate = null; public GettingBeaconsList (Context context,DelegateTaskCompleted delegate) { this.context = context; this.delegate = delegate; } // And constructor of second AsynTask is same as of First AsynTask Class private Context context = null; private DelegateTaskCompleted delegate = null; public GettingAirports (Context context,DelegateTaskCompleted delegate) { this.context = context; this.delegate = delegate; } 

onPostExecute de cada clase o subclase AsynTask, JSONArray se devuelve o se devuelve a la clase de llamada, que se muestra a continuación. En este caso, la clase de llamada es MainClass pero hay otras clases de actividad que usan las mismas clases AsynTask ( GettingBeaconsList y GettingAirports )

 protected void onPostExecute(String file_url) { pDialog.dismiss(); delegate.JsonArrayLoaded(gotNearestbeacons); } 

Ahora tengo un método (JsonArrayLoaded) en MainClass para abordar dos respuestas provenientes de dos tareas o servicios de fondo diferentes. Estoy usando la condición para averiguar qué servicio / clase o AsynTask se ejecuta.

Pero estoy preguntando cuál es la mejor manera de abordar este tipo de situaciones, como si tuviéramos 5 o más servicios en segundo plano en el futuro y simplemente devolvieran una matriz JSON, ¿así que tengo que hacer interfaces separadas para cada servicio?

¿Qué debería estar orientado a objetos en este caso?

La solución más simple que puedo pensar es modificar tu interfaz DelegateTaskCompleted para que se vea así:

 public interface DelegateTaskCompleted{ public void JsonArrayLoaded(AsyncTask task, JSONArray result); } 

Entonces su onPostExecute se enviará de vuelta como se muestra a continuación:

 protected void onPostExecute(String file_url) { pDialog.dismiss(); delegate.JsonArrayLoaded(this, gotNearestbeacons); } 

Finalmente, en su MainClass , puede tener una verificación condicional basada en el tipo de AsyncTask :

  @Override public void JsonArrayLoaded(AsyncTask task, JSONArray result) { if(task instanceof GettingBeaconsList) { // do stuff related to the beacon list } else if(task instanceof GettingAirports) { // do airport list stuff } } 

De esta forma, puede identificar fácilmente la AsyncTask que envía a través de la respuesta sin tener que rastrear cuál es, si una demora más que la otra, etc.


Alternativamente, tenga otra clase que amplíe AsyncTask pero agregue una variable abstracta para identificación.

 public class TrackableAsyncTask extends AsyncTask{ public abstract int getId(); public static final int ID_AIRPORT = 1; public static final int ID_BEACONS = 2; ... etc } 

Luego AsycTasks que su Airport and Beacon AsycTasks extienda esto en su lugar. Esto requerirá que implementen el método getId .

 public class GettingAirports extends AsyncTask { public int getId(){ return ID_AIRPORT; } } 

Y luego, en lugar de hacer una if (task instanceof GettingAirports) condicional if (task instanceof GettingAirports) , puede hacer una instrucción switch como la siguiente:

 switch(task.getId()){ case TrackableAsyncTask.ID_AIRPORT: // run airport code } 

Espero que esto ayude.

Hola, este código te ayudará

Esta es la interfaz para callback

 public interface CallbackReceiver { public void receiveData(Object result); } 

usa la clase Asynctask como clase Abstracta

 public abstract class JsonDataCallback extends AsyncTask implements CallbackReceiver { private ProgressDialog mProgressDialog; Handler handler; Runnable callback; Activity activity; public JsonDataCallback(Activity activity) { this.activity=activity; mProgressDialog = new ProgressDialog(activity); mProgressDialog.setMessage("Loading Please Wait."); mProgressDialog.setIndeterminate(false); mProgressDialog.setMax(100); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.setCancelable(true); } public abstract void receiveData(Object object); @Override protected void onPreExecute() { mProgressDialog =ProgressDialog.show(activity, "", "Please Wait",true,false); super.onPreExecute(); } @Override protected String doInBackground(String... aurl) { String results=""; // do stuff return results; } @Override protected void onPostExecute(String jsonData) { if (mProgressDialog != null || mProgressDialog.isShowing()){ mProgressDialog.dismiss(); } if(jsonData!=null) { receiveData(jsonData); } } } 

Y en tu código úsala así

 String url = ipaddress + "/GrantAdvanceList; JsonDataCallback callbackservice = new JsonDataCallback(yourActivity.this) { @Override public void receiveData(Object object) { jsonRecordsData = (String)object; //do stuff with call back data } }; callbackservice.execute(url, null, null); 

puedes reutilizar el código de esta manera, espero que esto te ayude. Gracias por adelantado.

También puede considerar Handler para lograr esto. Crear controlador en Actividad, pasar este objeto controlador a cada AsyncTask. En onPost llame a handler.sendEmptyMessage (CONSTANT_INT); En Handler handleMessage verifique msg.what en if o switch De esta forma solo se creará un objeto de handler y se usará en múltiples llamadas para async desde una actividad

Si entiendo tu problema correctamente, has extendido AsyncTask varias veces. El objective de cada una de estas subclases es pasar un JSONArray a una Actividad que implemente DelegateTaskCompleted, donde le hará algo. El desafío es que el “algo” que desea hacer a este JSONArray es diferente dependiendo de qué AsyncTask lo generó.

Saliendo de estas suposiciones, hay muchas maneras diferentes de diferenciar de qué AsyncTask proviene el JSONArray:

  1. Cree una variable estática, como un int, en su archivo de clase DelegateTaskCompleted para cada tipo de JSONArray que necesite manejar. Agregue un parámetro a JsonArrayLoaded del mismo tipo de esta variable. Luego, use sus declaraciones if-else o una statement switch que verifique esta variable con el conjunto y realice las acciones en su JSONArray a partir de ella.
  2. Si tiene acceso a lo que esté generando JSONArray, haga que el índice 0 de la matriz contenga información sobre cómo analizarlo. (Tal vez algo que se puede comparar con if-else o un cambio)
  3. Como sugirió, creando una interfaz separada para cada AsyncTask, o alternativamente una única interfaz con múltiples métodos.

Solo la opción 3 es una solución orientada a objetos, y como se ha señalado en los comentarios, no es muy buena debido a la escalabilidad. Esto de ninguna manera es una lista completa, solo algunas de mis ideas.

Sin embargo, me pregunto si vale la pena usar Interfaces, o al menos en la forma presentada. Como ya tiene diferentes subclases de AsyncTask para gestionar la generación de JSONArrays, ¿por qué no hacer lo que sea que esté haciendo con el método doInBackground() fuera del hilo principal, o al menos colocar esa lógica en alguna parte de esas clases, y simplemente devuelva los resultados (o posiblemente los rellene en una base de datos y los obtenga cuando sea necesario). Estoy pensando que puede haber una mejor manera de manejar su herencia AsyncTask que evite todas las interfaces, o al menos las use de manera diferente, como una sola interfaz implementada por todas sus AsyncTasks.

Sería realmente útil si puede aclarar su pregunta y explicar el tipo de operaciones que están realizando tanto AsyncTasks como su método JSONArrayLoaded , y quizás su razonamiento para usar las Interfaces tal como es. Es difícil dar una respuesta OO concreta o consejos sobre las mejores prácticas de OO con tan poca información sobre lo que su código realmente está haciendo y espera lograr.

Agregue una variable miembro a ambas clases AsyncTask, es decir,

 public class GettingBeaconsList extends AsyncTask public class GettingAirports extends AsyncTask 

como

 private int flag; 

y escribir setter para eso como

 public void setFlag(int flag) { this.flag = flag; } 

En MainClass:

 GettingBeaconsList beaconsList = new GettingBeaconsList(context,MainClass.this); beaconsList.setFlag(100); //Declare this flag in integer constant. beaconsList.execute(); GettingAirports airports = new GettingAirports(context, MainClass.this); airports.setFlag(200); airports.execute(); 

En ambas, las clases AsyncTask pasan el indicador con el método del delegado: –

 protected void onPostExecute(String file_url) { pDialog.dismiss(); delegate.JsonArrayLoaded(gotNearestbeacons, flag); //Change the signature of this method } 

De nuevo en MainClass para manejar la respuesta: –

 @Override public void JsonArrayLoaded(JSONArray result, int flag) { // Here check which Background task has been completed if(flag == 100) // GettingBeaconsList is executed if(flag == 200) // GettingAirport is executed. // bla bla or whatever here i write, does not matter if(ServiceBoolean == 1) { // Load activity 5 } else if( ServiceBoolean == 2) { // Load activity 6 } else if( ServiceBoolean==3 ) { // display Toast or Alert Box or load Activity number 8 } } 

Sugiero que simplemente use n clases internas para su actividad que implemente DelegateTaskCompleted . Es simple, eficiente, claro y de fácil comprensión (piense en el mantenimiento), y ya le está pasando al delegado cuando construye sus AsyncTasks, entonces, ¿podría ser que ya tenía este enfoque en mente?

 public class MainClass extends Activity { // probabnly not static ;) private final class BeaconsDelegate implements DelegateTaskCompleted ... private final class AirportsDelegate implements DelegateTaskCompleted ... }