模拟Android REST连接的最佳方式

时间:2015-07-09 22:57:37

标签: java android json rest

我正在制作一个通过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之间的中间方法,以实现应用程序和类的逻辑。

设计一个自动纠正/失败响应且独立于模型(用户,消息......)的同构连接系统的最佳方法是什么?

2 个答案:

答案 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);
        }
    });
}