我正在制作一个通过REST API连接到Web服务的Android应用程序,我对内部架构的设计感到困惑。
现在我有类Client.java,它的purpouse与服务器连接(ConnectionMethod是包含GET | POST值的Enum):
public class Client {
private AsyncHttpClient client = new AsyncHttpClient(); //I use com.loopj.AsyncHttpClient to connect
private ConnectionMethod method;
private RequestParams params = new RequestParams();
private AsyncHttpResponseHandler responseHandler = new JsonHttpResponseHandler(){
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
//Actions when connection success
}
@Override
public void onFailure(int statusCode, Header[] headers, JSONObject response, Throwable error) {
//Actions when connection fails
}
};
public Client (RequestParams params, ConnectionMethod method) {
this.params = params;
this.method = method;
}
public void addParameters (Map<String, String> parameters) {
for (Map.Entry<String, String> entry : parameters.entrySet()) {
this.params.put(entry.getKey(), entry.getValue());
}
}
public ServerResponse connect () {
RequestHandle handle;
if (this.method==ConnectionMethod.POST) {
handle = postRequest();
}
else {
handle = getRequest();
}
//How can I treat here different type of responses homogeneously?
}
private RequestHandle getRequest () {
return client.get(Constants.getEndpoint(), this.params, this.responseHandler);
}
private RequestHandle postRequest () {
return client.post(Constants.getEndpoint(), this.params, this.responseHandler);
}
}
从服务器请求信息的示例方法是:
public static void login (String login, String password) {
//This classes should be static or dynamic?
Map<String, String> map = new HashMap<String, String>();
map.put("login", login);
map.put("password", password);
map.put("method", "site_login");
Client c = new Client();
c.addParameters(map);
c.getRequest();
}
响应正确时,所有服务器响应都是JSON:{status:0,result:array / int / string},当响应不正确时,{status:-1,message:string}。
另外我想创建类来模拟JSON结果(User.java,Message.java ...)中的组件以及UI和API之间的中间方法,以实现应用程序和类的逻辑。
设计一个自动纠正/失败响应且独立于模型(用户,消息......)的同构连接系统的最佳方法是什么?
答案 0 :(得分:5)
有许多框架可以使整个过程变得更加容易。
例如,Retrofit
是用于将java类映射到REST调用的非常简单的框架。它带有gson
,它会自动反序列化从json到普通java对象的响应。
它还允许使用回调以及rxJava Observable。它也允许处理错误。
您可以查看示例应用:https://github.com/JakeWharton/u2020
答案 1 :(得分:2)
您正在描述已存在的工具。我最喜欢的是Retrofit,但还有其他人。 Retrofit可以处理成功和失败的响应,甚至可以将JSON直接映射到POJO。
我的API客户端
public class ApiClient {
private static ApiInterface sApiInterface;
public static ApiInterface getApiClient(Context context) {
//build the rest adapter
if (sApiInterface == null) {
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("example.com")
.build();
sApiInterface = restAdapter.create(ApiInterface.class);
}
return sApiInterface;
}
public interface ApiInterface {
@GET("/program/{id}")
void getProgram(@Path("id") int id, RetrofitCallback<Program> callback);
}
My RetrofitCallback
public class RetrofitCallback<S> implements Callback<S> {
private static final String TAG = RetrofitCallback.class.getSimpleName();
@Override
public void success(S s, Response response) {
}
@Override
public void failure(RetrofitError error) {
Log.e(TAG, "Failed to make http request for: " + error.getUrl());
Response errorResponse = error.getResponse();
if (errorResponse != null) {
Log.e(TAG, errorResponse.getReason());
if (errorResponse.getStatus() == 500) {
Log.e(TAG, "Handle Server Errors Here");
}
}
}
}
我的模特
public class Program {
@Expose
private doublea.models.Airtime Airtime;
@Expose
private String id;
@Expose
private String title;
@SerializedName("short_name")
@Expose
private String shortName;
@SerializedName("full_description")
@Expose
private String fullDescription;
@SerializedName("short_description")
@Expose
private String shortDescription;
@Expose
private doublea.models.Image Image;
@SerializedName("image")
@Expose
private String imageName;
@Expose
private List<Host> hosts = new ArrayList<Host>();
@Expose
private List<Category> categories = new ArrayList<Category>();
@Expose
private List<Airtime> airtimes = new ArrayList<Airtime>();
/** Getters and Setters */
public Program() {
}
如何使用。
private void executeProgramApiCall(int programId) {
ApiClient.getApiClient(this).getProgram(programId, new RetrofitCallback<Program>() {
@Override
public void success(Program program, Response response) {
super.success(program, response);
addDataToAdapter(program);
}
});
}