Как один интерфейс может использоваться для различных фоновых задач андроида?
Ну, у меня есть класс активности с двумя фоновыми задачами (Async-Task), которые были определены в двух отдельных классах, таких как
public class GettingBeaconsList extends AsyncTask<String, String, String>
public class GettingAirports extends AsyncTask<String, String, String>
которые инициализируются и выполняются в 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
}
}
}
Теперь в приведенном выше коде MainClass.this хранится как ссылка на интерфейс в подклассах AsynTask, например,
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 каждого класса или подкласса AsynTask, JSONArray возвращается или передается обратно вызывающему классу, показанному ниже. В этом случае вызывающий класс MainClass, но есть другие классы активности, которые используют те же классы AsynTask (GetBeaconsList и GettingAirports)
protected void onPostExecute(String file_url)
{
pDialog.dismiss();
delegate.JsonArrayLoaded(gotNearestbeacons);
}
Теперь у меня есть один метод (JsonArrayLoaded) в MainClass, чтобы решить два ответа, исходящих из двух разных фоновых задач или служб. Я использую условие, чтобы выяснить, какой сервис/класс или AsynTask выполняется.
Но я прошу наилучшего способа решить такой сценарий, как если бы у нас было 5 или более фоновых сервисов в будущем, и они просто возвращают массив JSON, поэтому мне нужно создавать отдельные интерфейсы для каждой службы?
Что должно быть объектно-ориентированным выходом в этом случае?
Ответы
Ответ 1
Самое упрощенное решение, о котором я могу думать, - это изменить ваш интерфейс DelegateTaskCompleted
так, чтобы он выглядел следующим образом:
public interface DelegateTaskCompleted{
public void JsonArrayLoaded(AsyncTask<String, String, String> task,
JSONArray result);
}
Затем ваш onPostExecute
отправит себя назад, как показано ниже:
protected void onPostExecute(String file_url)
{
pDialog.dismiss();
delegate.JsonArrayLoaded(this, gotNearestbeacons);
}
Наконец, в вашем MainClass
вы можете получить условную проверку на основе типа AsyncTask
:
@Override
public void JsonArrayLoaded(AsyncTask<String, String, String> task,
JSONArray result)
{
if(task instanceof GettingBeaconsList) {
// do stuff related to the beacon list
}
else if(task instanceof GettingAirports) {
// do airport list stuff
}
}
Таким образом, вы можете легко идентифицировать AsyncTask
, который отправляет через ответ, не отслеживая его, если он занимает больше времени, чем другой и т.д.
Кроме того, у вас есть другой класс, который расширяет AsyncTask
, но добавляет абстрактную переменную для идентификации.
public class TrackableAsyncTask extends AsyncTask<String, String, String>{
public abstract int getId();
public static final int ID_AIRPORT = 1;
public static final int ID_BEACONS = 2;
... etc
}
Затем используйте ваш аэропорт и маяк AsycTasks
. Это потребует от них реализации метода getId
.
public class GettingAirports extends AsyncTask<String, String, String> {
public int getId(){
return ID_AIRPORT;
}
}
А затем вместо выполнения условного if (task instanceof GettingAirports)
вы можете сделать оператор switch
, как показано ниже:
switch(task.getId()){
case TrackableAsyncTask.ID_AIRPORT:
// run airport code
}
Надеюсь, что это поможет.
Ответ 2
Привет, этот код поможет вам
Это интерфейс для обратного вызова
public interface CallbackReceiver {
public void receiveData(Object result);
}
использовать класс Asynctask как абстрактный класс
public abstract class JsonDataCallback extends AsyncTask<String, String, String> 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);
}
}
}
И в вашем коде используйте это как
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);
вы можете повторно использовать код таким образом, я надеюсь, что это вам поможет. Спасибо заранее.
Ответ 3
Если я правильно понял вашу проблему, вы несколько раз расширили AsyncTask. Цель каждого из этих подклассов - передать JSONArray в Activity, который реализует DelegateTaskCompleted, где вы будете что-то делать с ним. Задача состоит в том, что "что-то", что вы хотите сделать с этим JSONArray, отличается в зависимости от того, какой AsyncTask сгенерировал его.
Исходя из этих предположений, существует много разных способов, которыми вы можете отличить, от AsyncTask от JSONArray:
- Создайте статическую переменную, такую как int, в файле класса DelegateTaskCompleted для каждого типа JSONArray, который необходимо обработать. Добавьте параметр в
JsonArrayLoaded
того же типа этой переменной. Затем используйте ваши инструкции if-else или оператор switch, которые проверяют эту переменную на набор и выполняют действия на основе вашего JSONArray.
- Если у вас есть доступ к тому, что генерирует JSONArray, сделайте индекс 0 массива содержащим информацию о том, как его анализировать. (Возможно, вы можете сравнить с if-else или коммутатором)
- Как вы предположили, создание отдельного интерфейса для каждой AsyncTask или, альтернативно, одного интерфейса с несколькими методами.
Только опция 3 является объектно-ориентированным решением и, как было отмечено в комментариях, не является большой из-за масштабируемости. Это далеко не полный список, только некоторые из моих идей.
Мне интересно, хотя, стоит ли использовать интерфейсы вообще или, по крайней мере, в представленном порядке. Поскольку у вас уже есть разные подклассы AsyncTask для обработки генерации JSONArrays, почему бы не сделать то, что вы делаете с ними в методе doInBackground()
, от основного потока или, по крайней мере, поместить эту логику где-нибудь в этих классах, и просто верните результаты (или, возможно, запишите их в базу данных и получите их при необходимости). Я думаю, что может быть лучший способ обработать ваше наследование AsyncTask, которое позволяет избежать взаимодействия с интерфейсами или, по крайней мере, использовать их по-разному, например, один интерфейс, реализуемый всеми вашими AsyncTasks.
Было бы очень полезно, если вы сможете уточнить свой вопрос и объяснить тип операций, выполняемых как AsyncTasks, так и ваш метод JsonArrayLoaded
, и, возможно, ваши аргументы в пользу использования интерфейсов так, как вы. Трудно дать конкретный ответ OO или совет по лучшим практикам OO с такой небольшой информацией о том, что делает ваш код на самом деле, и надеется достичь.
Ответ 4
Вы также можете рассмотреть обработчик для достижения этого.
Создайте обработчик в Activity,
Передайте этот объект обработчика каждой AsyncTask.
В onPost вызов handler.sendEmptyMessage(CONSTANT_INT);
В Handler handleMessage check
msg.what в if или switch
Таким образом, будет создан только один объект обработчика и будет использоваться в нескольких
вызывает асинхронный вызов из одного действия.
Ответ 5
Добавьте одну переменную-член в оба класса AsyncTask i.e,
public class GettingBeaconsList extends AsyncTask<String, String, String>
public class GettingAirports extends AsyncTask<String, String, String>
как
private int flag;
и записывать установщик для этого как
public void setFlag(int flag)
{
this.flag = flag;
}
В 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();
В обоих классах AsyncTask пропускается флаг с помощью метода делегирования: -
protected void onPostExecute(String file_url)
{
pDialog.dismiss();
delegate.JsonArrayLoaded(gotNearestbeacons, flag);
//Change the signature of this method
}
Опять в MainClass для ответа: -
@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
}
}
Ответ 6
Я предлагаю вам просто использовать n внутренних классов для своей деятельности, которые реализуют DelegateTaskCompleted
. Это простой, эффективный, понятный и легко понятный (продуманный сервис) - и вы передаете делегат уже при создании своих AsyncTasks, так может быть, у вас уже был этот подход в вашем уме?
public class MainClass extends Activity {
// probabnly not static ;)
private final class BeaconsDelegate implements DelegateTaskCompleted ...
private final class AirportsDelegate implements DelegateTaskCompleted ...
}