10

さて、次のような 2 つの別々のクラスで定義された 2 つのバックグラウンド タスク (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 SubClasses に Interface Reference として格納されます

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に1 つのメソッド (JsonArrayLoaded) があり、2 つの異なるバックグラウンド タスクまたはサービスからの 2 つの応答に対処しています。条件を使用して、どのサービス/クラスまたは 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
}

次に、代わりに空港とビーコン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
}

お役に立てれば。

于 2013-01-21T16:53:49.020 に答える
6

これを実現するためにハンドラーを検討することもできます。Activityでハンドラーを作成し、このハンドラーオブジェクトを各AsyncTaskに渡します。onPost呼び出しhandler.sendEmptyMessage(CONSTANT_INT); ハンドラーでhandleMessagecheckmsg.what in ifまたはswitchこの方法では、ハンドラーの1つのオブジェクトのみが作成され、1つのアクティビティからの非同期の複数の呼び出し内で使用されます。

于 2013-01-22T09:41:23.520 に答える
6

私があなたの問題を正しく理解していれば、あなたは AsyncTask を何度か拡張しています。これらの各サブクラスの目的は、DelegateTaskCompleted を実装する Activity に JSONArray を渡すことであり、そこで何らかの操作を行います。課題は、この JSONArray に対して実行したい「何か」が、それを生成した AsyncTask によって異なることです。

これらの仮定から外れて、JSONArray がどの AsyncTask から来たかを区別できるさまざまな方法があります。

  1. DelegateTaskCompleted クラス ファイルで、処理する必要がある JSONArray の型ごとに、int などの静的変数を作成します。JsonArrayLoadedこの変数と同じ型のパラメーターを追加します。次に、if-else ステートメントまたは switch ステートメントを使用して、この変数をセットに対してチェックし、それに基づいて JSONArray に対してアクションを実行します。
  2. JSONArray を生成しているものにアクセスできる場合は、Array の 0 インデックスに解析方法に関する情報を含めます。(おそらく、if-else やスイッチと比較できるもの)
  3. あなたが提案したように、AsyncTaskごとに個別のインターフェースを作成するか、複数のメソッドを持つ単一のインターフェースを作成します。

オプション 3 のみがオブジェクト指向ソリューションであり、コメントで指摘されているように、スケーラビリティのために優れたソリューションではありません。これは決して完全なリストではなく、私の考えの一部です。

ただし、インターフェイスを使用する価値があるかどうか、または少なくとも提示された方法で使用する価値があるかどうかは疑問です。JSONArrays の生成を処理するための AsyncTask のさまざまなサブクラスが既にあるのでdoInBackground()、メイン スレッドから離れたメソッド内でそれらに対して行っていることを実行しないでください。または、少なくともそのロジックをそれらのクラスのどこかに配置して、単に返してください。結果 (または、データベースに詰め込み、必要なときに取得する可能性があります)。AsyncTask の継承を処理するためのより良い方法があるかもしれないと考えています。これは、すべての AsyncTask によって実装されている単一のインターフェイスなど、インターフェイスをすべて一緒に回避するか、少なくとも別の方法で使用します。

質問を明確にし、AsyncTasks とJSONArrayLoadedメソッドの両方が実行している操作の種類、およびおそらくインターフェイスをそのまま使用する理由を説明できれば、非常に役立ちます。コードが実際に行っていることや達成したいことについての情報がほとんどないため、具体的な OO の回答や OO のベスト プラクティスに関するアドバイスを提供することは困難です。

于 2013-01-17T00:03:15.117 に答える
4

1つのメンバー変数を両方のAsyncTaskクラスに追加します。

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
    } 


}
于 2013-01-22T14:44:24.623 に答える
0

を実装するアクティビティには、単に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 に答える