OkHttp快速上手

日志拦截器

注意两种拦截器的不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class LoggingInterceptor implements Interceptor {
@Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
logger.info(String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long t2 = System.nanoTime();
logger.info(String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
return response;
}
}
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor())
.build();

Headers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
Request request = new Request.Builder()
.url("https://api.github.com/repos/square/okhttp/issues")
.header("User-Agent", "OkHttp Headers.java")
.addHeader("Accept", "application/json; q=0.5")
.addHeader("Accept", "application/vnd.github.v3+json")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println("Server: " + response.header("Server"));
System.out.println("Date: " + response.header("Date"));
System.out.println("Vary: " + response.headers("Vary"));
}

配置

1
2
3
4
5
6
7
8
9
10
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(cacheDirectory, cacheSize);
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.cache(cache)
.retryOnConnectionFailure(true)
.build();

单个配置

单个别请求需要单独设置时

1
2
3
OkHttpClient client1 = client.newBuilder()
.readTimeout(500, TimeUnit.MILLISECONDS)
.build();

post 表单

1
2
3
4
5
6
7
8
9
10
11
12
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
RequestBody formBody = new FormBody.Builder()
.add("search", "Jurassic Park")
.build();
Request request = new Request.Builder()
.url("https://en.wikipedia.org/w/index.php")
.post(formBody)
.build();
Response response = client.newCall(request).execute();

post String

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
String postBody = ""
+ "Releases\n"
+ "--------\n"
+ "\n"
+ " * _1.0_ May 6, 2013\n"
+ " * _1.1_ June 15, 2013\n"
+ " * _1.2_ August 11, 2013\n";
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody))
.build();
Response response = client.newCall(request).execute();
}

post a file

1
2
3
4
5
6
7
8
9
10
11
12
13
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
File file = new File("README.md");
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
.build();
Response response = client.newCall(request).execute();
}

post multipart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private static final String IMGUR_CLIENT_ID = "...";
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
// Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "Square Logo")
.addFormDataPart("image", "logo-square.png",
RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
.build();
Request request = new Request.Builder()
.header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
.url("https://api.imgur.com/3/image")
.post(requestBody)
.build();
Response response = client.newCall(request).execute())
}

cancel 和 response

注意cancel和response的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//当请求没有结束,会调用 onFailure 所以添加判断call.isCanceled()
call.cancel();
//查询是否取消
call.isCanceled();
//查询是否执行过
call.isExecuted();
//code >= 200 && code < 300 成功的状态码
response.isSuccessful()
//读取一次数据流就会关闭,再出读取为null
response.body().string()
//记得关闭resopnse
Response.close();
Response.body().close();
Response.body().source().close();
Response.body().charStream().close();
Response.body().byteString().close();
Response.body().bytes();
Response.body().string();
//Call对象只能执行一次请求
Call reCall=client.newCall(call.request()); //获取另一个相同配置的Call对

简单封装

封装成一个工具类,直接上代码

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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
public class OkHttpHelper {
public static OkHttpHelper mInstance;
private OkHttpClient mClient;
private Handler mHandler;
//构造方法 初始化请求客户端
private OkHttpHelper(Context context) {
File sdcache = context.getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024;
mClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.addInterceptor(new LoggingInterceptor())
.cache(new Cache(sdcache.getAbsoluteFile(), cacheSize))
.build();
//ui线程looper
mHandler = new Handler(Looper.getMainLooper());
}
public static OkHttpHelper getInstance(Context context) {
if (mInstance == null) {
synchronized (OkHttpHelper.class) {
if (mInstance == null) {
mInstance = new OkHttpHelper(context);
}
}
}
return mInstance;
}
//返回ok
public OkHttpClient getOkClient() {
return mClient;
}
//根据标记取消任务
public void cancelCallWithTag(String tag) {
//取消还未运行的
for (Call call : mClient.dispatcher().queuedCalls()) {
if (call.request().tag().equals(tag))
call.cancel();
}
//取消正在运行的
for (Call call : mClient.dispatcher().runningCalls()) {
if (call.request().tag().equals(tag))
call.cancel();
}
}
//get异步请求
public void getRequest(@NonNull String url, String tag, Map<String, String> params, OkCallBack callBack) {
if (params == null) {
params = new HashMap<>();
}
if (TextUtils.isEmpty(tag)) {
tag = url;
}
//拼接地址
String requestUrl = urlJoint(url, params);
Request request = new Request.Builder()
.url(requestUrl)
.tag(tag)
.build();
Call call = mClient.newCall(request);
dealResult(call, callBack);
}
//post异步请求
public void postRequest(@NonNull String url, String tag, Map<String, String> params, OkCallBack callBack) {
//请求体
RequestBody requestBody;
if (params == null) {
params = new HashMap<>();
}
if (TextUtils.isEmpty(tag)) {
tag = url;
}
FormBody.Builder builder = new FormBody.Builder();
for (Map.Entry<String, String> map : params.entrySet()) {
String key = map.getKey();
String value;
//判断值是否是空的
if (map.getValue() == null) {
value = "";
} else {
value = map.getValue();
}
//把key和value添加到formbody中
builder.add(key, value);
}
requestBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.tag(tag)
.build();
Call call = mClient.newCall(request);
dealResult(call, callBack);
}
//post异步请求及文件,自己构造requestBody
public void postRequestMultipart(@NonNull String url, String tag, RequestBody requestBody, OkCallBack callBack) {
if (TextUtils.isEmpty(tag)) {
tag = url;
}
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.tag(tag)
.build();
Call call = mClient.newCall(request);
dealResult(call, callBack);
}
//post异步上传单文件
public void postOnlyFile(@NonNull String url, MediaType mediaType, String tag, File file, OkCallBack callBack) {
if (TextUtils.isEmpty(tag)) {
tag = url;
}
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(mediaType,file))
.tag(tag)
.build();
Call call = mClient.newCall(request);
dealResult(call, callBack);
}
//处理结果
private void dealResult(Call call, final OkCallBack callBack) {
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
sendFailCallback(call, e, callBack);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
sendSuccessCallBack(call,response, callBack);
}
});
}
//成功响应
private void sendSuccessCallBack(final Call call, final Response response, final OkCallBack callBack) {
if (callBack != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
try {
callBack.onResponse(call,response);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
//失败响应
private void sendFailCallback(final Call call, final IOException e, final OkCallBack callBack) {
mHandler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
callBack.onError(call, e);
}
}
});
}
/**
* 拼接url和请求参数
*
* @param url url
* @param params key value
* @return String url
*/
private static String urlJoint(String url, Map<String, String> params) {
StringBuilder endUrl = new StringBuilder(url);
boolean isFirst = true;
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
if (isFirst && !url.contains("?")) {
isFirst = false;
endUrl.append("?");
} else {
endUrl.append("&");
}
endUrl.append(entry.getKey());
endUrl.append("=");
endUrl.append(entry.getValue());
}
return endUrl.toString();
}
}