带回调的通用asyncTask(用于Web服务)

时间:2013-01-15 21:17:18

标签: android web-services android-asynctask

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

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

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

我的问题是:我无法定义Callback接口吗?例如这一个:

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

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

1)运行Web服务的方法

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

3)RequestCallback实例(可以是匿名内联实例,我可以从onSuccess()更新UI)

4)Activity的上下文(显示ProgressDialog()所必需的,所以我仍然需要一种方法来防止配置更改异常等等...),

你觉得这个设计好吗?它可以节省数百行代码......

2 个答案:

答案 0 :(得分: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的子类中,我将准确地告诉它响应类是什么(Movie,Clip ...)
    希望这有帮助。

答案 1 :(得分:0)

如果你已经使用它并且它适合你,那么是的,它是有意义的,使它通用,并节省重新实现相同的事情数十次的时间(和错误)。如果您发现自己复制粘贴大部分代码而几乎没有差异,则应将其转换为库函数或某种类。否则,如果您以后发现问题,则必须在十几个地方修复它。如果你想到一个更好的方法来做事情,这甚至不重要 - 它仍然比一个地方更容易改变它。

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