AsyncTask Android-设计模式和返回值

AsyncTask Android-设计模式和返回值,android,http,design-patterns,android-asynctask,Android,Http,Design Patterns,Android Asynctask,我正在编写一个在外部Web服务器上验证登录凭据的应用程序-因此我有一个基本问题,即创建一个登录屏幕,提交后将向后台服务器发送HTTP请求,而不会导致UI挂起-同时向用户提供一个ProgressDialog 我的问题在于,我想编写一个扩展AsyncTask的通用HTTP请求类,因此当我调用.execute()时,我将传递可能包含类似“post”的字符串参数,当调用doInBackground时,将看到“post”字符串,然后将这些参数转发到我的类中相应的调用中。伪代码类似于 public clas

我正在编写一个在外部Web服务器上验证登录凭据的应用程序-因此我有一个基本问题,即创建一个登录屏幕,提交后将向后台服务器发送HTTP请求,而不会导致UI挂起-同时向用户提供一个ProgressDialog

我的问题在于,我想编写一个扩展AsyncTask的通用HTTP请求类,因此当我调用
.execute()
时,我将传递可能包含类似“post”的字符串参数,当调用
doInBackground
时,将看到“post”字符串,然后将这些参数转发到我的类中相应的调用中。伪代码类似于

public class HTTPOperations extends AsyncTask<String, Void, String>
{
doInBackground(String... string1,additionalParams)
{
  if string1.equals "post"
      response = httpPost(additionalParams)
       return response;
}

httpPost(params)
{
// do http post request
}
}
公共类HTTPOperations扩展异步任务
{
doInBackground(字符串…字符串1,附加参数)
{
如果string1.1等于“post”
响应=httpPost(附加参数)
返回响应;
}
httpPost(参数)
{
//执行http post请求
}
}
这就是我所能想到的,除了为我希望发出的每个HTTP Post/GET etc请求创建一个类并扩展ASyncTask之外

这就引出了我的下一个问题,如果HTTP POST成功并且返回了一个身份验证令牌,我如何访问这个令牌

因为new httpOperations.execute()不会从doInBackground返回字符串,而是返回类型为的值


对不起,如果这不合理,我一点也不明白。如果需要,请要求详细说明。AsyncTask设计模式和思想非常受欢迎。

如果要为类似的内容设计可重用任务,则需要确定可重用的返回类型。这是你自己的设计决定。问问自己,“我的HTTP操作在调用它们的机制和处理它们的数据的机制上是否相似?”如果是这样,您可以设计一个类来实现这两个功能。如果没有,您可能需要不同的类来执行不同的远程操作

在我个人使用中,我有一个将键值对附加到的对象,常见的返回类型是。这是HTTPGET和Post的返回类型,在我的场景中似乎可以正常工作,因为我在异常HTTP结果情况下抛出异常,如404。这种设置的另一个优点是,将参数附加到get或post的代码非常相似,因此这种逻辑非常容易构造


一个例子如下(psuedo):

然后,在您的代码中,您要在哪里进行下载:

DownloadCallback dc = new DownloadCallback(){
   public void onSuccess(String downloadedString){
     Log.d("TEST", "Downloaded the string: "+ downloadedString);
   }
   public void onFailure(Exception e){
     Log.d("TEST", "Download had a serious failure: "+ e.getMessage());
   }
 }

 DownloadAsyncTask dlTask = new DownloadAsyncTask(dc);
然后在DownloadAsyncTask的构造函数中,存储DownloadCallback,当下载完成或失败时,调用与事件对应的下载回调上的方法。所以

public class DownloadAsyncTask extends AsyncTask <X, Y, Z>(){
  DownloadCallback dc = null;

  DownloadAsyncTask(DownloadCallback dc){
    this.dc = dc;
  }

  ... other stuff ...

  protected void onPostExecute(String string){
    dc.onSuccess(string);
  }
}
公共类下载AsyncTask扩展AsyncTask(){
DownloadCallback dc=null;
DownloadAsyncTask(DownloadCallback dc){
this.dc=dc;
}
…其他东西。。。
受保护的void onPostExecute(字符串){
dc.onSuccess(字符串);
}
}

我要重申,我认为为了你自己的利益,你应该把HttpEntities传回去。字符串现在看起来似乎是个好主意,但当您想在http调用后面执行更复杂的逻辑时,它确实会带来麻烦。当然,这取决于你。希望这会有所帮助。

假设web api的数据格式是json,我的设计模式:

普通类
1.MyAsyncTask:扩展AsyncTask
2.BackgroundBase:服务器的参数
3.API_库:来自服务器的参数
4.MyTaskCompleted:回调接口

public class MyAsyncTask<BackgroundClass extends BackgroundBase,APIClass extends API_Base> extends AsyncTask<BackgroundClass, Void, APIClass> {
    private ProgressDialog pd ; 
    private MyTaskCompleted listener;
    private Context cxt;
    private Class<APIClass> resultType;
    private String url;
    private int requestCode;    

    public MyAsyncTask(MyTaskCompleted listener, Class<APIClass> resultType, int requestCode, String url){
        this.listener = listener;
        this.cxt = (Context)listener;
        this.requestCode = requestCode;
        this.resultType = resultType;
        this.url = url;
    }
    public MyAsyncTask(MyTaskCompleted listener, Class<APIClass> resultType, int requestCode, String url, ProgressDialog pd){
            this(listener, resultType, requestCode, url);
            this.pd = pd;
            this.pd.show();
    }   

    @Override
    protected APIClass doInBackground(BackgroundClass... params) {
        APIClass result = null;
        try {           
            //do something with url and params, and get data from WebServer api
            BackgroundClass oParams = params[0];
            String sUrl = url + "?d=" + URLEncoder.encode(oParams.getJSON(), "UTF-8");
            String source = "{\"RtnCode\":1, \"ResultA\":\"result aaa\", \"ResultB\":\"result bbb\"}";

            //to see progressdialog
            Thread.sleep(2000);

            result = new com.google.gson.Gson().fromJson(source, resultType);           
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

     @Override
     protected void onPostExecute(APIClass result) {
        super.onPostExecute(result);

        try {
            if(pd != null && pd.isShowing())
                pd.dismiss();

            API_Base oApi_Base = (API_Base)result;          
            listener.onMyTaskCompleted(result , this.requestCode);                      
        } catch (Exception e) {
            e.printStackTrace();
        }           
    }

}
public class API_Base {
    public int RtnCode;

    public String getJSON(Context context) throws Exception
    {
        return new com.google.gson.Gson().toJson(this);
    }


    public String toString(){
        StringBuilder sb = new StringBuilder();

        for (Field field : this.getClass().getFields()) {
            try {
                field.setAccessible(true); 
                Object value = field.get(this); 
                if (value != null) {
                    sb.append(String.format("%s = %s\n", field.getName(), value));
                }
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }

        }

        return sb.toString();
    }

}
public class BackgroundBase {

    public String getJSON() throws Exception
    {       
        return new com.google.gson.Gson().toJson(this);
    }

}
public interface MyTaskCompleted {
    void onMyTaskCompleted(API_Base oApi_Base, int requestCode) ;
}
公共类MyAsyncTask扩展了AsyncTask{
私营部门;
私有MyTaskCompleted侦听器;
私有上下文cxt;
私有类
输入参数:ActionA
输出参数:RtnCode,结果

API 2.
输入参数:ActionB
输出参数:RtnCode,ResultB

带示例的类:
1.MyActivity:扩展活动并实现MyTaskCompleted
2.MyConfig:utility类,我在这里设置requestCode
3.BackgroundActionA、BackgroundActionB:api输入参数的模型类
4.API_ActionA、API_ActionB:API输出参数的模型类

public class MyActivity extends Activity implements MyTaskCompleted {
    ProgressDialog pd;
    Button btnActionA, btnActionB;
    TextView txtResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_layout);
        btnActionA = (Button)findViewById(R.id.btn_actionA);
        btnActionB = (Button)findViewById(R.id.btn_actionB);
        txtResult = (TextView)findViewById(R.id.txt_result);

        btnActionA.setOnClickListener(listener_ActionA);
        btnActionB.setOnClickListener(listener_ActionB);

        pd = new ProgressDialog(MyActivity.this);
        pd.setTitle("Title");
        pd.setMessage("Loading");
    }

    Button.OnClickListener listener_ActionA = new Button.OnClickListener(){

        @Override
        public void onClick(View v) {
            //without ProgressDialog
            BackgroundActionA oBackgroundActionA = new BackgroundActionA("AAA");
            new MyAsyncTask<BackgroundActionA, API_ActionA>(MyActivity.this, 
                                                            API_ActionA.class, 
                                                            MyConfig.RequestCode_actionA,
                                                            "http://www.google.com/action/a").execute(oBackgroundActionA);
        }

    };
    Button.OnClickListener listener_ActionB = new Button.OnClickListener(){

        @Override
        public void onClick(View v) {
            //has ProgressDialog
            BackgroundActionB oBackgroundActionB = new BackgroundActionB("BBB");
            new MyAsyncTask<BackgroundActionB, API_ActionB>(MyActivity.this, 
                                                            API_ActionB.class, 
                                                            MyConfig.RequestCode_actionB,
                                                            "http://www.google.com/action/b",
                                                            MyActivity.this.pd).execute(oBackgroundActionB);
        }

    };

    @Override
    public void onMyTaskCompleted(API_Base oApi_Base, int requestCode) {
        // TODO Auto-generated method stub
        if(requestCode == MyConfig.RequestCode_actionA){
            API_ActionA oAPI_ActionA = (API_ActionA)oApi_Base;
            txtResult.setText(oAPI_ActionA.toString());

        }else if(requestCode == MyConfig.RequestCode_actionB){
            API_ActionB oAPI_ActionB = (API_ActionB)oApi_Base;
            txtResult.setText(oAPI_ActionB.toString());

        }

    }

}
public class MyConfig {
    public static String LogTag = "henrytest";

    public static int RequestCode_actionA = 1001;
    public static int RequestCode_actionB = 1002;
}
public class BackgroundActionA extends BackgroundBase {
    public String ActionA ;

    public BackgroundActionA(String actionA){
        this.ActionA = actionA;
    }

}
public class BackgroundActionB extends BackgroundBase {
    public String ActionB;

    public BackgroundActionB(String actionB){
        this.ActionB = actionB;
    }
}
public class API_ActionA extends API_Base {
    public String ResultA;
}
public class API_ActionB extends API_Base {
    public String ResultB;
}
公共类MyActivity扩展活动实现MyTaskCompleted{
进展性帕金森病;
按钮btnActionA、btnActionB;
TextView txtResult;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
//TODO自动生成的方法存根
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
btnActionA=(按钮)findViewById(R.id.btn_action a);
btnActionB=(按钮)findViewById(R.id.btn_actionB);
txtResult=(TextView)findViewById(R.id.txt\u结果);
setOnClickListener(listener\u ActionA);
btnActionB.setOnClickListener(listener\u ActionB);
pd=新建进度对话框(MyActivity.this);
pd.设定所有权(“所有权”);
pd.setMessage(“加载”);
}
Button.OnClickListener监听器\u ActionA=新建Button.OnClickListener(){
@凌驾
公共void onClick(视图v){
//无进程对话框
背景行动A oBackgroundActionA=新背景行动A(“AAA”);
新建MyAsyncTask(MyActivity.this,
API_ActionA.class,
MyConfig.RequestCode_actionA,
"http://www.google.com/action/a)执行(oBackgroundActionA);
}
};
Button.OnClickListener监听器\u ActionB=新建Button.OnClickListener(){
@凌驾
公共void onClick(视图v){
//进行对话
BackgroundActionB oBackgroundActionB=新的BackgroundActionB(“BBB”);
新建MyAsyncTask(MyActivity.this,
API_ActionB.class,
public class MyActivity extends Activity implements MyTaskCompleted {
    ProgressDialog pd;
    Button btnActionA, btnActionB;
    TextView txtResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_layout);
        btnActionA = (Button)findViewById(R.id.btn_actionA);
        btnActionB = (Button)findViewById(R.id.btn_actionB);
        txtResult = (TextView)findViewById(R.id.txt_result);

        btnActionA.setOnClickListener(listener_ActionA);
        btnActionB.setOnClickListener(listener_ActionB);

        pd = new ProgressDialog(MyActivity.this);
        pd.setTitle("Title");
        pd.setMessage("Loading");
    }

    Button.OnClickListener listener_ActionA = new Button.OnClickListener(){

        @Override
        public void onClick(View v) {
            //without ProgressDialog
            BackgroundActionA oBackgroundActionA = new BackgroundActionA("AAA");
            new MyAsyncTask<BackgroundActionA, API_ActionA>(MyActivity.this, 
                                                            API_ActionA.class, 
                                                            MyConfig.RequestCode_actionA,
                                                            "http://www.google.com/action/a").execute(oBackgroundActionA);
        }

    };
    Button.OnClickListener listener_ActionB = new Button.OnClickListener(){

        @Override
        public void onClick(View v) {
            //has ProgressDialog
            BackgroundActionB oBackgroundActionB = new BackgroundActionB("BBB");
            new MyAsyncTask<BackgroundActionB, API_ActionB>(MyActivity.this, 
                                                            API_ActionB.class, 
                                                            MyConfig.RequestCode_actionB,
                                                            "http://www.google.com/action/b",
                                                            MyActivity.this.pd).execute(oBackgroundActionB);
        }

    };

    @Override
    public void onMyTaskCompleted(API_Base oApi_Base, int requestCode) {
        // TODO Auto-generated method stub
        if(requestCode == MyConfig.RequestCode_actionA){
            API_ActionA oAPI_ActionA = (API_ActionA)oApi_Base;
            txtResult.setText(oAPI_ActionA.toString());

        }else if(requestCode == MyConfig.RequestCode_actionB){
            API_ActionB oAPI_ActionB = (API_ActionB)oApi_Base;
            txtResult.setText(oAPI_ActionB.toString());

        }

    }

}
public class MyConfig {
    public static String LogTag = "henrytest";

    public static int RequestCode_actionA = 1001;
    public static int RequestCode_actionB = 1002;
}
public class BackgroundActionA extends BackgroundBase {
    public String ActionA ;

    public BackgroundActionA(String actionA){
        this.ActionA = actionA;
    }

}
public class BackgroundActionB extends BackgroundBase {
    public String ActionB;

    public BackgroundActionB(String actionB){
        this.ActionB = actionB;
    }
}
public class API_ActionA extends API_Base {
    public String ResultA;
}
public class API_ActionB extends API_Base {
    public String ResultB;
}