3

常に次のアプローチを使用して、Web サービス要求を行う多くの Android アプリを既に開発しています。

Web サービス リクエストを行う必要があるすべてのアクティビティで、 inAsyncTaskを表示し、ProgressDialoginonPreExecute()で Web サービスを呼び出しdoInBackground、progressDialog を閉じて UI の結果を から更新するインナーを定義しますonPostExecute()

私の懸念は次のとおりです。それを行うためのより良い(より短い)方法はありますか?すべてのアクティビティですべてのコードを繰り返すことは理にかなっていますか? 私はたくさんグーグルで検索してきましたが、何も見つかりませんでした。

私の質問は: Callback インターフェイスを定義できませんでしたか? たとえば、これ:

public interface RequestCallback {
    public void onSuccess(Whatever whatever);
    public void onError(ErrorCode errorCode, String message);
}

AsyncRequest... 次に、AsyncTask 定義と ProgressDialogshow()およびdismiss()ステートメントをラップする外部クラス (たとえば、 ) を定義します。したがって、すべてのアクティビティはそのクラスをインスタンス化し、次のパラメーターを渡すだけで済みます。

1) 実行する Web サービスのメソッド

2) Web サービスのそのメソッドのすべてのパラメーターを含むバンドル

3) RequestCallback インスタンス (UI を更新できる匿名のインライン インスタンスである可能性がありますonSuccess())

4)アクティビティのコンテキスト(ProgressDialog()を表示する必要があるため、構成変更の例外を防ぐ方法が必要です...)、

これはいいデザインだと思いませんか?何百行ものコードを節約できます...

4

2 に答える 2

1

あなたのアプローチは、私が私のプロジェクトで行ったことです。そして、あなたが言ったように多くのコードを節約しました。私はそれについて何の不満もありません。しかし、ここで私があなたに伝えたいいくつかの問題があります:

  1. AsyncTaskバックグラウンド スレッドを実行するたびに新しいインスタンスを作成して、コールバックを山積みしないようにする必要があります。
  2. 進行状況ダイアログについてはSingleton、同時に多くのダイアログを表示しないため、 として使用します。バックグラウンド ジョブを呼び出すとダイアログが表示され、コールバックで閉じられます。これが私がしたことです:

    private void showProgressDialog(String strMess){
        if(null == progressDialog){
          progressDialog = new ProgressDialog(MainActivity.this);           
        }
        if(!progressDialog.isShowing()){
          progressDialog.setMessage(strMess);           
          progressDialog.show();
        }
    }
    
    private void hideProgressDialog(){
      if(null != progressDialog && progressDialog.isShowing()){
        progressDialog.dismiss();
      }
     }
    
    void someMethod(){
     showProgressDialog("Loading...");
     doBackgroundJob(param, new RequestCallBack() {
    
     public void onRequestCompleted(String message, boolean isSuccess) {
                hideProgressDialog();
                if(isSuccess){
    
                }else{
                    //do something on error
                }
            }
        });
    
      }
    
  3. これはオプションです。特定のクラスの代わりに通知するインターフェイスを定義しました。応答ごとに 1 つのクラスを使用するため、基本クラスでは、応答が何であるかは気にしません。はい、これ:

    public interface OnRequestCompleted<TResponse>  {
       void requestCompleted(TResponse response);
    }
    
    public abstract class BaseRequest<TResponse> implements IRequest{
          protected OnRequestCompleted<TResponse> delegate;
          protected Class<TResponse> responseClass;
    
          @Override
          public void send() {
             new HttpTask().execute();
          }
    
          private class HttpTask extends AsyncTask<Void, Void, String> {
          //...
    
          @Override
          protected void onPostExecute(String result) {
              if (null != response && null != delegate) {
              delegate.requestCompleted(response);
          }
         }
       }
    
      // the response example
      public class GroupResponse {
      public static class Clip {
              public int clipId;
          public String detail;
      }
    
      public static class Movie {       
      public int movieId;
              public String detail;
      }  
    
     }
    

    のサブクラスではBaseRequest、応答クラス (ムービー、クリップ...) が何であるかを正確に伝え
    ます。

于 2013-01-16T04:33:08.167 に答える
0

すでに使用していてうまく機能する場合は、それを汎用的にして、同じものを何十回も再実装する時間(およびバグ)を節約することは理にかなっています。コードの大きなセクションをほとんどまたはまったく違いなくコピーして貼り付けることに気付いた場合は、それをライブラリ関数またはある種のクラスに変換する必要があります。そうしないと、後で問題が見つかった場合は、12か所で修正する必要があります。後で物事を行うためのより良い方法を考えても問題ではありません。1ダースよりも1か所で変更する方が簡単です。

私があなたのソリューションで抱えている唯一の本当の問題は、プログレスバーを追加しないことです-呼び出し元のコードとonSuccess/onError実装で処理します。そうすれば、UIを表示する必要のないバックグラウンド呼び出しに再利用することもできます。UIの決定をデータ取得コードからできるだけ遠ざけるようにしています。MVCパターンは優れています。

于 2013-01-15T21:26:34.867 に答える