我正在编写一个验证外部Web服务器上的登录凭据的应用程序 - 所以我有一个基本的问题:创建一个登录屏幕,当提交时会在后台向服务器发送HTTP请求而不会导致UI挂起 - 同时向用户提供ProgressDialog。
我的问题在于,我想编写一个扩展AsyncTask的通用HTTP Request类,所以当我调用.execute()
时,我将传递String参数,这些参数可能包含类似'post'的内容,以及{{1调用它会看到'post'字符串,然后将这些参数转发到我班级的相应调用中。伪代码就像
doInBackground
这是我能想到的,除了为我希望制作的每个HTTP Post / GET等请求创建一个类并扩展ASyncTask ......
这引出了我的下一个问题,如果HTTP POST成功并返回一个身份验证令牌,我该如何访问此令牌?
因为新的httpOperations.execute(),不会从doInBackground返回字符串,而是返回类型
的值对不起,如果这没有意义,我根本无法解决这个问题。如果需要,请索取详细说明。 AsyncTask的设计模式和想法受到了极大的欢迎。
答案 0 :(得分:23)
如果您正在为此类设计可重用任务,则需要确定可重用的返回类型。这是您的设计决定。问问自己,“我的HTTP操作在调用它们的机制和处理它们的数据方面是否相似?”如果是这样,您可以设计一个类来执行这两个操作。如果没有,您可能需要为不同的远程操作使用不同的类。
在我个人的使用中,我有一个对象,我附加了键值对,常见的返回类型是HttpEntity。这是HTTP Get和Post的返回类型,这似乎在我的场景中正常工作,因为我在异常的HTTP结果情况下抛出异常,例如404.此设置的另一个好处是将参数附加到get的代码或者帖子非常相似,所以这个逻辑很容易构建。
一个例子就是这样的(psuedo):
public interface DownloadCallback {
void onSuccess(String downloadedString);
void onFailure(Exception exception);
}
然后在你的代码中,你去哪里下载:
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);
}
}
我要重申,我认为为了自己的利益,你应该传回HttpEntities。字符串现在似乎是一个好主意,但是当你想要在http调用后面做更复杂的逻辑时,它确实会导致麻烦。当然,这取决于你。希望这会有所帮助。
答案 1 :(得分:1)
假设web api的数据格式是json,我的设计模式:
普通班级
1.MyAsyncTask:扩展AsyncTask
2.BackgroundBase:服务器的参数
3.API_Base:来自服务器的参数
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) ;
}
例如,让我们在一个活动中调用两个api
假设:
API 1。http://www.google.com/action/a
输入参数:ActionA
输出参数:RtnCode,ResultA
API 2。http://www.google.com/action/b
输入参数:ActionB
输出参数:RtnCode,ResultB
类示例:
1.MyActivity:扩展Activity并实现MyTaskCompleted
2.MyConfig:实用程序类,我在这里设置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;
}
这种设计模式的优势:
1.多重的优势
2.只需为新api添加模型类,例如:BackgroundActionA和API_ActionA
3.通过回调函数中的不同requestCode确定哪个API:onMyTaskCompleted