Okhttp3的封装 搞定常用的请求

开篇

这篇博客写下Okhttp的封装,作为安卓最应用最广泛的网络请求框架,okhttp也是被玩出了各种姿势,虽然已经帮我们把一个原生的网络请求封装精简了很多,不过为了更加的方便,还是再进行一层的封装,这里的封装包括了常用的GET,POST,DELETE,PUT的请求,其中post包括了基于json格式的请求,以及表单形式的请求,因为上传文件基本都是用的表单去提交的,基本这一套封装可以搞定安卓应用里面一般的网络请求了。

具体封装

首先看看全部的文件
全部文件
包括了3个接口文件,和3个实现类文件。

接口文件

请求参数的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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();
}

方法具体的作用 注释都写得很清楚了,接下来

请求响应接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface IResponse {
/**
* 响应码
* @return
*/
int getCode();
/**
* 返回的数据
* @return
*/
String getData();
}

请求方法接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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类型的键值对。
然后就是具体的实现类了

实现类

请求参数实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
**
* @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请求的参数。

响应接口实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
**
* @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;
}
}

这里没什么好说的,最后是重点了

请求方法实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* @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拿到响应码和服务器端返回的数据。

使用方法

使用起来还是比较方便的,看看基本的使用,如下

1
2
3
4
5
6
7
8
9
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。

总结

合理的封装除了能让我们的项目的业务逻辑看起来更加清晰,还能锻炼面向对象的思维,多折腾下总没错,就先到这里了。

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 开篇
  2. 2. 具体封装
    1. 2.1. 接口文件
      1. 2.1.1. 请求参数的接口
      2. 2.1.2. 请求响应接口
      3. 2.1.3. 请求方法接口
    2. 2.2. 实现类
      1. 2.2.1. 请求参数实现类
      2. 2.2.2. 响应接口实现类
      3. 2.2.3. 请求方法实现类
  3. 3. 使用方法
  4. 4. 总结
,