在Android中,有一种比使用带有参数的AsyncTask
更好的方法来确定要调用的REST端点吗?
e.g。我需要打电话:
www.test.com/api/room/id
www.test.com/api/room/id/booking
AsyncTask
专为单个 doInBackground()
方法而设计,例如,拨打:
www.test.com/api/room/id
我不想为每个REST端点创建多个 AsyncTasks
实例。
后端会使用:
RoomClient = new RoomClient();
roomClient.getID()
roomClient.getBookingForRoom()
在Android中看起来我需要
class RoomFromId extends AsyncTask
...
call www.test.com/api/room/id
class BookingForRoom extends AsyncTask
..
call www.test.com/api/room/id/booking
我在Android应用程序中的理想情况是编写一个可以在后台调用所有REST端点的休息客户端的习惯用法,而不必在自己的 AsyncTask
。我更喜欢使用Android而不是第三方库。
答案 0 :(得分:2)
创建一个从AsyncTask扩展的泛型类,它返回从YourBaseModel扩展的泛型类型的响应(我称之为M)
public class HttpRequest<M extends BaseModel> extends AsyncTask<Object, Integer, M> {
public enum RequestMethod {
GET("GET"), POST("POST");
private final String requestMethod;
RequestMethod(String requestMethod) {
this.requestMethod = requestMethod;
}
public String getValue() {
return requestMethod;
}
}
private Context context = null;
private String url;
private OnResponseCallback onResponseCallback;
private OnFailureCallback onFailureCallback;
private RequestMethod method;
private int statusCode;
private String message;
private Class<M> responseModel;
private Object body = null;
private String token;
private HttpRequest() {
}
@Override
protected M doInBackground(Object... voids) {
try {
HttpURLConnection connection = getHttpConnection();
connection.connect();
int statusCode = connection.getResponseCode();
if (connection.getResponseCode() / 100 != 2) {
this.statusCode = statusCode;
this.message = connection.getResponseMessage();
return JsonParser.getErrorBodyAs(responseModel, statusCode,
message);
}
InputStreamReader streamReader = new
InputStreamReader(connection.getInputStream());
return JsonParser.getErrorBodyAs(responseModel, statusCode,
convertInputStreamToString(streamReader));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private HttpURLConnection getHttpConnection() throws IOException {
URL url = new URL(this.url);
HttpURLConnection connection = (HttpURLConnection)
url.openConnection();
connection.setRequestMethod(method.getValue());
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Authorization", "Bearer " + token);
connection.setReadTimeout(30000);
connection.setConnectTimeout(30000);
if (method == RequestMethod.POST) {
connection.setDoInput(true);
connection.setDoOutput(true);
if (body != null) {
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(new Gson().toJson(body));
writer.flush();
}
}
return connection;
}
@Override
protected void onPostExecute(M m) {
if (m == null) {
if ((message != null && !message.equals("") && statusCode != 0)) {
HttpException httpException = new HttpException(statusCode, message);
onFailureCallback.onFailure(httpException);
} else {
onFailureCallback.onFailure("unknown error");
}
} else {
onResponseCallback.onResponse(m);
}
}
public static String convertInputStreamToString(InputStreamReader inputStreamReader) throws IOException {
if (inputStreamReader == null) {
return "";
}
BufferedReader reader = new BufferedReader(inputStreamReader);
StringBuilder stringBuilder = new StringBuilder();
String inputLine;
String result;
while ((inputLine = reader.readLine()) != null) {
stringBuilder.append(inputLine);
}
reader.close();
inputStreamReader.close();
return stringBuilder.toString();
}
static public class Builder {
HttpRequest t = new HttpRequest();
public Builder setContext(Context context) {
t.context = context;
return this;
}
public Builder setUrl(String url) {
t.url = url;
return this;
}
public Builder setRequestMethod(RequestMethod method) {
t.method = method;
return this;
}
public Builder setBody(Object body) {
t.body = body;
return this;
}
public Builder setToken(String token) {
t.token = token;
return this;
}
public HttpRequest get() {
return t;
}
public HttpRequest run(Class<?> responseTypeClass,
OnResponseCallback onResponseCallback,
OnFailureCallback onFailureCallback) {
t.responseModel = responseTypeClass;
t.onResponseCallback = onResponseCallback;
t.onFailureCallback = onFailureCallback;
t.execute();
return t;
}
public Builder() {
}
}
}
你可以像这样使用它:
HttpRequest.Builder builder = new HttpRequest.Builder();
builder.setContext(context)
.setRequestMethod(HttpRequest.RequestMethod.POST)
.setBody(body)
.setUrl("http://url")
.run(YourResponeModel.class, new OnResponseCallback() {
@Override
public void onResponse(Object response) {
},
new OnFailureCallback() {
@Override
public void onFailure(Object throwable) {
}
});
答案 1 :(得分:1)
在您创建的扩展AsyncTask的类中,您可以创建一个构造函数并传递您想要/需要的任何内容。
在这种情况下,您可以定义一个扩展AsyncTask的类ApiManager,并传递一个定义要调用的方法的常量。 在该构造函数中,您可以将变量保存到ApiManager对象,然后在doInBackground方法中进行检查。
所以,要打电话给房间/身份证你可以做类似的事情:
new ApiManager(ROOM_FROM_ID).execute(...
打电话给房间/ id /预订:
new ApiManager(BOOKING_FOR_ROOM).execute(...
ApiManager类应该是这样的:
class ApiManager extends AsyncTask... {
private int method;
public ApiManager(int method) {
this.method = method;
}
...
}