3

我已经开发了许多发出 Web 服务请求的 Android 应用程序,总是使用以下方法:

在每个需要发出 Web 服务请求的活动中,我定义了一个AsyncTask显示ProgressDialogin的内部,在 中onPreExecute()进行 Web 服务调用doInBackground,并关闭 progressDialog 并从 更新 UI 中的结果onPostExecute()

我担心的是:有更好(更短)的方法吗?在每个活动中重复所有这些代码是否有意义?我一直在谷歌搜索,但我什么也没找到。

我的问题是:我不能定义一个回调接口吗?例如这个:

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

...然后定义一个外部类,例如AsyncRequest,包装 AsyncTask 定义和 ProgressDialogshow()dismiss()语句。因此,所有活动只需要实例化该类,并传入以下参数:

1)Web服务运行的方法

2) 一个包含该 Web 服务方法的所有参数的 Bundle

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. 这是一个可选的,我定义了一个接口来通知而不是特定的类,对于每个响应我使用一个类,所以在基类中,我不在乎响应是什么。就这个:

    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

如果您已经使用它并且它对您有用,那么将其通用化并节省数十次重新实现同一事物的时间(和错误)是有意义的。如果您发现自己复制粘贴了几乎没有差异的大段代码,您应该将其转换为某种库函数或类。否则,如果您以后发现问题,您将不得不在十几个地方修复它。即使您以后想出更好的方法来做事也没关系-在一个地方更改它比十几个地方更容易。

我对您的解决方案唯一真正的问题是我不会向它添加进度条 - 我会在调用代码和 onSuccess/onError 实现中处理它。这样,您还可以将它重用于不需要设置 UI 的后台调用。我尽量让我的 UI 决策远离数据抓取代码,MVC 模式很好。

于 2013-01-15T21:26:34.867 回答