10

好吧,我有一个带有两个后台任务(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;
}

每个 AsynTask 类或子类的 onPostExecute,JSONArray 返回或传回调用类,如下所示。在这种情况下,调用类是MainClass但还有其他活动类使用相同的 AsynTask 类(GettingBeaconsListGettingAirports

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

现在我在MainClass中有一个方法 (JsonArrayLoaded)来处理来自两个不同后台任务或服务的两个响应。我正在使用条件来确定执行了哪个服务/类或 AsynTask。

但是我要求最好的方法来解决这种情况,如果我们将来有 5 个或更多后台服务,它们也只是返回一个 JSON 数组,所以我需要为每个服务创建单独的接口吗?

在这种情况下,面向对象的出路应该是什么?

4

6 回答 6

14

这是回调的接口

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

您可以通过这种方式重用代码。

于 2013-01-17T09:50:18.740 回答
7

我能想到的最简单的解决方案是修改您的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
}

然后让你的 Airport 和 BeaconAsycTasks扩展它。这将要求他们实施该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
}

希望这可以帮助。

于 2013-01-21T16:53:49.020 回答
6

如果我正确理解您的问题,您已经扩展了 AsyncTask 几次。这些子类中的每一个的目标是将 JSONArray 传递给实现了 DelegateTaskCompleted 的 Activity,您将在其中对其执行某些操作。挑战在于,您想要对此 JSONArray 执行的“某事”会有所不同,具体取决于 AsyncTask 生成它的方式。

抛开这些假设,有很多不同的方法可以区分 JSONArray 来自哪个 AsyncTask:

  1. 在您的 DelegateTaskCompleted 类文件中为它需要处理的每种 JSONArray 类型创建一个静态变量,例如一个 int。添加一个JsonArrayLoaded与此变量相同类型的参数。然后,使用您的 if-else 语句或 switch 语句来检查该变量与该集合并基于它对您的 JSONArray 执行操作。
  2. 如果您有权访问生成 JSONArray 的任何内容,请使 Array 的 0 索引包含有关如何解析它的信息。(也许您可以将其与 if-else 或 switch 进行比较)
  3. 正如您所建议的,为每个 AsyncTask 创建一个单独的接口,或者一个具有多种方法的单个接口。

只有选项 3 是面向对象的解决方案,正如评论中所指出的,由于可扩展性,这不是一个很好的解决方案。这绝不是一个完整的列表,只是我的一些想法。

不过,我想知道,是否值得使用接口,或者至少以呈现的方式。既然您已经有不同的 AsyncTask 子类来处理生成 JSONArrays,为什么不在主线程之外的方法中对它们执行任何操作doInBackground(),或者至少将该逻辑放在这些类中的某个位置,然后返回结果(或者可能将它们填充到数据库中并在需要时获取它们)。我认为可能有更好的方法来处理您的 AsyncTask 继承,它可以避免所有接口,或者至少以不同的方式使用它们,例如所有 AsyncTask 都实现一个接口。

如果您能够澄清您的问题并解释 AsyncTasks 和您的JSONArrayLoaded方法正在执行的操作类型,以及您以您的方式使用接口的原因,那将非常有帮助。很难给出一个具体的 OO 答案或关于 OO 最佳实践的建议,而关于您的代码实际在做什么和希望实现的信息很少。

于 2013-01-17T00:03:15.117 回答
6

您也可以考虑使用 Handler 来实现这一点。在Activity中创建handler,把这个handler对象传给每个AsyncTask。在 onPost 调用 handler.sendEmptyMessage(CONSTANT_INT); 在 Handler handleMessage 检查 msg.what in if 或 switch 这样一来,只有一个处理程序对象将被创建并在多个调用中使用一个活动的异步

于 2013-01-22T09:41:23.520 回答
4

向两个 AsyncTask 类添加一个成员变量,即

public class GettingBeaconsList extends AsyncTask<String, String, String> 
public class GettingAirports extends AsyncTask<String, String, String> 

作为

private int flag;

并为此编写setter

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
    } 


}
于 2013-01-22T14:44:24.623 回答
0

我建议你简单地为你的 Activity 使用n 个内部类来实现DelegateTaskCompleted. 它简单、高效、清晰且易于理解(想想维护)——当您构建 AsyncTasks 时,您已经传递了委托,那么您是否已经想到了这种方法?

public class MainClass extends Activity {
    // probabnly not static ;)
    private final class BeaconsDelegate implements DelegateTaskCompleted ...
    private final class AirportsDelegate implements DelegateTaskCompleted ...
}
于 2013-01-23T09:20:32.113 回答