基于okhttp封装网络库 (3)
前言:根据之前封装的库来写一个具体的请求豆瓣 api 的任务类!
准备工作:
通过 豆瓣 api,查看可知获取某个图书信息的 api 长这样。
由第一点可知我们请求的 主机地址是 api.douban.com,具体图书 api则是 /v2/book/isbn/:name,请求方式是 GET,所以我们先来完成做以上三点。
1. BookDetailTask
//修改主机地址
public class HttpConfig {
public static final String HOST = "https://api.douban.com";
}
public class BookDetailTask extends GETRequest {
private String mIsbn;
public BookDetailTask(String isbn ) {
super( );
mIsbn = isbn;
}
@Override
public String getApi() {
return "/v2/book/isbn/" + mIsbn;
}
@Override
public int getHttpMethod() {
return HttpMethod.GET;
}
@Override
public Class getModelClass() {
return BookBean.class;
}
}
//GETRequest 让具体的任务类不用实现 BaseRequest 中 GET 请求方式中无用的接口。
public abstract class GETRequest extends BaseRequest {
public MediaType getMediaType() {
return null;
}
protected String getRequestString() {
return null;
}
}
但是我们通过 Postman 调试工具可以发现豆瓣返回的参数并不是一二级协议的格式。那怎么办呢?很简单,只要对我们类库进行一个简单的修改就可以,具体来讲就是手动构一个 HttpResponse出来,其实就是 okhttp 层接受到的 Response code 和 message 参数取出来。
2. 构造 HttpResponse
- 首先对 getResponse 方法进行修改。
private HttpResponse<T> getResponse(Response response) throws IOException {
ResponseBody body = response.body();
//fastJson 中的 api
Object data = JSON.parseObject(body.string(),getModelClass());
HttpResponse<T> httpResponse = new HttpResponse<T>();
httpResponse.data = (T) data;
httpResponse.code = response.code();
httpResponse.message = response.message();
return httpResponse;
}
- 其次对同步/异步模块修改
public HttpResponse<T> execute() throws IOException {
Response response = this.mClient.newCall(buildRequest()).execute();
int code = response.code();
if (code == 200) {
//正常请求
// ResponseBody body = response.body();
// return getResponse(body);
return getResponse(response);
} else {
return null;
}
}
//修改点在 onResponse 中将原来的 resonse.body() 注释掉,直接传入 response.
public boolean enqueue(final HttpCallback<T> callback) {
if (mCall == null) {
mCall = mClient.newCall(buildRequest());
mCall.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
HttpResponse response = new HttpResponse(ResponseCode.NET_ERROR, ResourceHelper.getString(R.string.neterror), null);
mDelivery.postResponse(callback, BaseRequest.this, response, e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
HttpResponse<T> httpResponse = null;
try {
// httpResponse = getResponse(response.body());
httpResponse = getResponse(response);
mDelivery.postResponse(callback, BaseRequest.this, httpResponse, null);
} catch (IOException e) {
httpResponse = new HttpResponse(ResponseCode.NET_ERROR, ResourceHelper.getString(R.string.neterror), null);
mDelivery.postResponse(callback, BaseRequest.this, httpResponse, e);
} catch (JSONException e) {
httpResponse = new HttpResponse(ResponseCode.JSON_ERROR, ResourceHelper.getString(R.string.jsonparseerror), null);
mDelivery.postResponse(callback, BaseRequest.this, httpResponse, e);
}
}
});
} else {
if (mCall.isCanceled() || mCall.isExecuted()) {
Log.e("TAG", "cancel executed");
}
}
return true;
}
3.使用 BookDetailTask 完成调用。
// 封装这个 Action 类的目的是避免在业务层过多的调用 BookDetailTask 造成代码混乱,避免冗余同时也与业务层开发解耦。
public class BookDetailAction {
//只要调用者传入 IGetBookCB 回调接口就可以收到消息。
public static void getBookkDetail(String result, final IGetBookCB cb ) {
final BookDetailTask task = new BookDetailTask(result);
task.enqueue(new HttpCallback() {
@Override
public void onResponse(BaseRequest request, Object data) {
if (cb != null) {
cb.onConnectSuccess(data);
}
}
@Override
public void onFailure(BaseRequest request, Exception e, int code, String message) {
if (cb !=null){
cb.onConnectFailed(code,message);
}
}
});
}
public interface IGetBookCB {
void onConnectSuccess(Object o);
void onConnectFailed(int code ,String message);
}
}