好吧,我有一个带有两个后台任务(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数组,所以我需要为每个服务建立单独的接口吗?
对于这种情况,应该面向对象的方式是什么?
答案 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:
JsonArrayLoaded
。然后,使用if-else语句或switch语句来检查该变量,并根据它对JSONArray执行操作。 只有选项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 ...
}