这篇博客写下Okhttp的封装,作为安卓最应用最广泛的网络请求框架,okhttp也是被玩出了各种姿势,虽然已经帮我们把一个原生的网络请求封装精简了很多,不过为了更加的方便,还是再进行一层的封装,这里的封装包括了常用的GET,POST,DELETE,PUT的请求,其中post包括了基于json格式的请求,以及表单形式的请求,因为上传文件基本都是用的表单去提交的,基本这一套封装可以搞定安卓应用里面一般的网络请求了。
具体封装首先看看全部的文件
包括了3个接口文件,和3个实现类文件。
接口文件
请求参数的接口
public interface IRequest {
public static final String POST = "POST";
public static final String GET = "GET";
public static final String DELETE = "DELETE";
public static final String PUT = "PUT";
/**
* 请求方式
* @param method
*/
void setMethod(String method);
/**
* 指定请求头
* @param key
* @param value
*/
void setHeader(String key, String value);
/**
* 指定请求信息
* @param key
* @param value
*/
void setBody(String key, Object value);
/**
* 提供给执行库请求行URL
* @return
*/
String getUrl();
/**
* 提供给执行库请求行URL
* @return
*/
Map<String,String> getHeader();
/**
* 请求体
* @return
*/
String getBody();
}
方法具体的作用 注释都写得很清楚了,接下来
请求响应接口
public interface IResponse {
/**
* 响应码
* @return
*/
int getCode();
/**
* 返回的数据
* @return
*/
String getData();
}
请求方法接口
public interface IHttpClient {
IResponse get(IRequest request);
/**
* json格式的post
* @param request
* @return
*/
IResponse post(IRequest request);
/**
* 表单类型的post
* @param request
* @param map
* @param file
* @return
*/
IResponse upload_image_post(IRequest request, Map<String, Object> map, File file);
IResponse delete(IRequest request);
IResponse put(IRequest request);
}
这里就用的图片上传,其它文件上传也只是改一下文件类型一样。需要注意的是,这里的上传图片的post方法传入的参数是使用了一个map类型的键值对。
然后就是具体的实现类了
实现类
请求参数实现类
**
* @author Legend
* @data by on 2017/11/23.
* @description
*/
public class RequestImpl implements IRequest {
private String method = POST;
private String url;
private Map<String,String> header;
private Map<String,Object> body;
public RequestImpl(String url) {
/**
* 初始化公共参数和头部信息
*/
this.url = url;
header = new HashMap();
body = new HashMap<>();
}
@Override
public void setMethod(String method) {
this.method = method;
}
@Override
public void setHeader(String key, String value) {
header.put(key,value);
}
@Override
public void setBody(String key, Object value) {
body.put(key,value);
}
@Override
public String getUrl() {
if (GET.equals(method)) {
// 组装post请求参数
for (String key : body.keySet()) {
url = url.replace("${"+key+"}",body.get(key).toString());
}
}
return url;
}
@Override
public Map<String, String> getHeader() {
return header;
}
@Override
public String getBody() {
// 组装post请求参数
if (body != null) {
return new Gson().toJson(this.body,HashMap.class);
} else {
return "{}";
}
}
}
这里用到了Gson来组装post请求的参数。
响应接口实现类
**
* @author Legend
* @data by on 2017/11/23.
* @description
*/
public class ResponseImpl implements IResponse {
public static final int STATE_UNKNOW_ERROR = 100001;
public static int STATE_OK = 200;
private int code;
private String data;
@Override
public String getData() {
return data;
}
@Override
public int getCode () {
return code;
}
public void setCode(int code) {
this.code = code;
}
public void setData(String data) {
this.data = data;
}
}
这里没什么好说的,最后是重点了
请求方法实现类
/**
* @author Legend
* @data by on 2017/11/23.
* @description
*/
public class OkHttpClientImpl implements IHttpClient {
OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
.build();
@Override
public IResponse get(IRequest request) {
/**
* 解析业务参数
*/
// 指定请求方式
request.setMethod(IRequest.GET);
Map<String,String> header = request.getHeader();
Request.Builder builder = new Request.Builder();
for (String key : header.keySet()) {
builder.header(key,header.get(key));
}
builder.url(request.getUrl()
).get();
Request okRequest = builder.build();
return execute(okRequest);
}
@Override
public IResponse post(IRequest request) {
request.setMethod(IRequest.POST);
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
RequestBody requestBody = RequestBody.create(mediaType,request.getBody().toString());
Map<String,String> header = request.getHeader();
Request.Builder builder = new Request.Builder();
for (String key : header.keySet()) {
builder.header(key,header.get(key));
}
builder.url(request.getUrl())
.post(requestBody);
Request okRequest = builder.build();
return execute(okRequest);
}
@Override
public IResponse upload_image_post(IRequest request,Map<String,Object> map,File file) {
/**
* 实现文件上传
*/
request.setMethod(IRequest.POST);
MediaType MEDIA_TYPE_IMAGE = MediaType.parse("image/*");
MultipartBody.Builder requestBody = new MultipartBody
.Builder().setType(MultipartBody.FORM);
if (file != null) {
requestBody.addFormDataPart("image",file.getName(),
RequestBody.create(MEDIA_TYPE_IMAGE,file));
}
if (map != null) {
// map 里面是请求中所需要的 key 和 value
for (Map.Entry entry : map.entrySet()) {
requestBody.addFormDataPart(valueOf(entry.getKey()), valueOf(entry.getValue()));
}
}
Map<String,String> header = request.getHeader();
Request.Builder builder = new Request.Builder();
for (String key : header.keySet()) {
builder.header(key,header.get(key));
}
builder.url(request.getUrl())
.post(requestBody.build());
Request okRequest = builder.build();
return execute(okRequest);
}
@Override
public IResponse delete(IRequest request) {
request.setMethod(IRequest.DELETE);
Map<String,String> header = request.getHeader();
Request.Builder builder = new Request.Builder();
for (String key : header.keySet()) {
builder.header(key,header.get(key));
}
builder.url(request.getUrl())
.delete(null);
Request okRequest = builder.build();
return execute(okRequest);
}
@Override
public IResponse put(IRequest request) {
request.setMethod(IRequest.PUT);
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
RequestBody requestBody = RequestBody.create(mediaType,request.getBody().toString());
Map<String,String> header = request.getHeader();
Request.Builder builder = new Request.Builder();
for (String key : header.keySet()) {
builder.header(key,header.get(key));
}
builder.url(request.getUrl())
.put(requestBody);
Request okRequest = builder.build();
return execute(okRequest);
}
private IResponse execute(Request request) {
ResponseImpl commonResponse = new ResponseImpl();
try {
Response response = mOkHttpClient.newCall(request).execute();
// 设置状态码
commonResponse.setCode(response.code());
String body = response.body().string();
// 设置响应数据
commonResponse.setData(body);
} catch (IOException e) {
e.printStackTrace();
commonResponse.setCode(ResponseImpl.STATE_UNKNOW_ERROR);
commonResponse.setData(e.getMessage());
}
return commonResponse;
}
}
每个请求方法把参数准备好后都是放到execute方法去执行,最后我们可以通过返回的commonResposne拿到响应码和服务器端返回的数据。
使用方法使用起来还是比较方便的,看看基本的使用,如下
IRequest request = new RequestImpl(这里传入url);
//设置请求头,这里要几个就setHeader几次
request.setHeader(key,value);
// 设置请求体 同上
request.setBody(key,value);
// 获取一个okhttpclient实例
IHttpClient mHttpClient = new OkHttpClientImpl();
// 得到服务器端返回的结果
IResponse response = mHttpClient.get(request);
得到返回结果,就可以做我们想要的操作了,可以写一个回调把请求结果传入进行,用handler向主线程发送响应结果,这里就不多说了。
然后是表单类型的请求,可以用一个Map来组装请求参数,然后直接传入方法即可,不需要上传文件的话就可以直接传null。
合理的封装除了能让我们的项目的业务逻辑看起来更加清晰,还能锻炼面向对象的思维,多折腾下总没错,就先到这里了。