一个界面如何用于不同的后台android任务?

时间:2013-01-10 08:16:11

标签: java android oop interface android-asynctask

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

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

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

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

对于这种情况,应该面向对象的方式是什么?

6 个答案:

答案 0 :(得分:13)

您好此代码可以帮助您

这是回调的界面

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

你可以用这种方式重用代码,希望这对你有所帮助。提前谢谢。

答案 1 :(得分: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
}

然后让您的机场和灯塔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 :(得分:6)

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

关于这些假设,有许多不同的方法可以区分JSONArray来自哪个AsyncTask:

  1. 在DelegateTaskCompleted类文件中为它需要处理的每种类型的JSONArray创建一个静态变量,例如int。将参数添加到此变量的相同类型的JsonArrayLoaded。然后,使用if-else语句或switch语句来检查该变量,并根据它对JSONArray执行操作。
  2. 如果您可以访问生成JSONArray的任何内容,请使Array的0索引包含有关如何解析它的信息。 (也许你可以用if-else或者开关来比较)
  3. 正如您所建议的那样,为每个AsyncTask创建一个单独的接口,或者使用多个方法创建一个单独的接口。
  4. 只有选项3是面向对象的解决方案,正如评论中指出的那样,由于可扩展性而不是很好的解决方案。这绝不是一个完整的清单,只是我的一些想法。

    我想知道,如果根本不使用接口,或者至少以所呈现的方式使用接口是值得的。由于您已经有不同的AsyncTask子类来处理生成JSONArrays,为什么不在主线程的doInBackground()方法中对它们做任何事情,或者至少将那个逻辑放在那些类,只返回结果(或者可能将它们填入数据库并在需要时获取它们)。我认为可能有更好的方法来处理你的AsyncTask继承,它们避免了所有的接口,或者至少使用它们不同,例如所有AsyncTasks都实现了一个接口。

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

答案 3 :(得分:6)

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

答案 4 :(得分:4)

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

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

as

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
    } 


}

答案 5 :(得分:0)

我建议您只为实现DelegateTaskCompleted的Activity使用 n 内部类。它简单,高效,清晰且易于理解(想想维护) - 当您构建AsyncTasks时,您已经通过了委托,那么您是否已经考虑过这种方法?

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