网络请求框架-OkHttp使用方法总结
OkHttp
2019-2-18 17:45 - QG2017移动组 - 张艺隽OkHttp是一个HTTP+HTTP/2的客户端。
- 来自官方的说明:
An HTTP+HTTP/2 client for Android and Java applications.目前OkHttp在github上star的数量高达30k+,仅次于Retrofit,很多大型公司及APP都开始或已经对OkHttp进行封装。Retrofit2.0开始内置OkHttp框架。
学习和使用OkHttp的原因:
- 自动为你的网络请求添加缺失的header(例如 Content-Length, Transfer-Encoding, User-Agent等);
- 对重定向(302)的连接进行跟进访问;
- 使用连接池减少延迟、增加网络吞吐量;
- 使用TSL协议为网络访问保障安全及数据完整性;
Okhttp3基本使用
1. 开始使用 添加依赖
implementation("com.squareup.okhttp3:okhttp:3.13.1")
2. GET 1. 同步 使用OkHttpClient.newCall(Requset).execute()来同步获取Response
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
Request request = new Request.Builder()
.url("https://publicobject.com/helloworld.txt")
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
Headers responseHeaders = response.headers();
for (int i = 0;
i < responseHeaders.size();
i++) {
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
}System.out.println(response.body().string());
}
}
2. 异步 使用OkHttpClient.newCall(Requset).enqueue(Callback)来异步获取Response
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}@Override
public void onResponse(Call call, Response response) throws IOException {
try (ResponseBody responseBody = response.body()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
Headers responseHeaders = response.headers();
for (int i = 0, size = responseHeaders.size();
i < size;
i++) {
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
}System.out.println(responseBody.string());
}
}
});
3. POST 1. posting a String
MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown;
charset=utf-8");
String postBody = "content";
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody))
.build();
2. posting Stream
public void run() throws Exception {RequestBody requestBody = new RequestBody() {
@Override
public MediaType contentType() {
return MEDIA_TYPE_MARKDOWN;
}@Override
public void writeTo(BufferedSink sink) throws IOException {
sink.writeUtf8("Numbers\n");
}
};
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(requestBody)
.build();
}
3. posting a File
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();
4. posting form parameters
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();
5. posting a multipart request
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();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
}
常用的MediaType:
- json : application/json
- xml : application/xml
- png : image/png
- jpg : image/jpeg
- gif : imge/gif
- 对于Request:
- 使用header()会将上一次header()设置的value取代
- 对于想叠加的value,使用addHeader()来实现
- 对于Response:
- 使用header(key)来获取对应的value,如果一个key对应一个value,则返回最后一个value;如果没有对应的value,则返回null
- 对于一个key对应多个value的情况,使用headers(key)获得value的列表(List)
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();
try (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"));
}
}
5. 缓存 【网络请求框架-OkHttp使用方法总结】缓存类java文档:Javadoc-Class Cache
wiki-Response Caching
public CacheResponse(File cacheDirectory) throws Exception {
int cacheSize = 10 * 1024 * 1024;
// 10 MiB
Cache cache = new Cache(cacheDirectory, cacheSize);
client = new OkHttpClient.Builder()
.cache(cache)
.build();
}
- OkHttpClient应使用单例模式,如果多个client同时对缓存目录进行访问将会抛出异常,甚至导致程序崩溃。
public ConfigureTimeouts() throws Exception {
client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
}
7. 修改单次配置 有时候需要在网络访问中修改client的某些属性,这时候可以用到OkHttpClient.newBuilder() 来产生新的OkHttpClient实例。新的实例和原来的client配置一致,并且共享连接池。
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
Request request = new Request.Builder()
.url("http://httpbin.org/delay/1") // This URL is served with a 1 second delay.
.build();
// Copy to customize OkHttp for this request.
OkHttpClient client1 = client.newBuilder()
.readTimeout(500, TimeUnit.MILLISECONDS)
.build();
try (Response response = client1.newCall(request).execute()) {
System.out.println("Response 1 succeeded: " + response);
} catch (IOException e) {
System.out.println("Response 1 failed: " + e);
}// Copy to customize OkHttp for this request.
OkHttpClient client2 = client.newBuilder()
.readTimeout(3000, TimeUnit.MILLISECONDS)
.build();
try (Response response = client2.newCall(request).execute()) {
System.out.println("Response 2 succeeded: " + response);
} catch (IOException e) {
System.out.println("Response 2 failed: " + e);
}
}
8. 授权证书 测试地址
wiki-Handling authentication
使用Credentials.basic(username, password)生成证书:
private final OkHttpClient client;
public Authenticate() {
client = new OkHttpClient.Builder()
.authenticator(new Authenticator() {
@Override
public Request authenticate(Route route, Response response) throws IOException {
if (response.request().header("Authorization") != null) {
return null;
// Give up, we've already attempted to authenticate.
}System.out.println("Authenticating for response: " + response);
System.out.println("Challenges: " + response.challenges());
String credential = Credentials.basic("jesse", "password1");
return response.request().newBuilder()
.header("Authorization", credential)
.build();
}
})
.build();
}
9. 拦截器 OkHttp 拦截器的一些骚操作
链接介绍了一些不错的小技巧,例如解决Retrofit更改path比较麻烦的缺点、Header的统一添加、日志抓取等。
结语:OkHttp真的是十分强大的开源框架,配合Retrofit更是锦上添花。尽管如此,目前仍需要复习基础,熟记Android原生网络请求写法。#OkHttp - 完()
推荐阅读
- parallels|parallels desktop 解决网络初始化失败问题
- android第三方框架(五)ButterKnife
- 猎杀IP
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- 自媒体形势分析
- 数学大作战
- 2018.03.18
- 星期天的下午茶(一)
- 08黑龙江迟淑荣弯柳树网络学院第五期学习赵宗瑞老师主讲的(传统文化与身心健康)教育体系心得体会
- https请求被提早撤回