一.OkHttp简介
OkHttp是一个高效的HTTP客户端,它有以下默认特性:
支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接
连接池减少请求延时
透明的GZIP压缩减少响应数据的大小
缓存响应内容,避免一些完全重复的请求
当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0
二 OkHttp 的使用
添加okhttp 依赖
implementation 'com.squareup.okhttp3:okhttp:3.12.3'
execute 这个方法是同步请求 enqueue这个方法是异步请求
1.1:异步get请求
new OkHttpClient 构造OkHttp对象
//OkHttpClient okHttpClient = new OkHttpClient().build()
2:创建Reques对象
String url="ttp://gank.io/api/data/%E7%A6%8F%E5%88%A9/20/1";
Request request = new Request.Builder()
.url(url)
.get() //默认就是get请求 可以不写
.build;
3:通过上述两步构造call对象 //
Call call = okHttpClient.newCall(request);
4:通过Call#enqueue(Callback)方法来提交异步请求;
call.enqueue(new Callback() {
@Override // 请求网络数据失败的方法
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: ");
}
@Override //请求网络数据成功的方法
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) { //判断是否请求成功
String string = response.body().string(); //读取的网络数据转化成字符串
} else {
Log.i("tag", "onResponse: " + response.message()); //不成功的话输出响应的通知消息
}
}
});
1.2:get()同步请求
前面几个步骤和异步方式一样,只是最后一部是通过 Call#execute() 来提交请求,注意这种方式会阻塞调用线程,
所以在Android中应放在子线程中执行,否则有可能引起ANR异常,Android3.0 以后已经不允许在主线程访问网络。
new OkHttpClient;
创建Reques对象
String url="http://gank.io/api/data/%E7%A6%8F%E5%88%A9/20/1";
// Request request = new Request.Builder()
.url(url)
.get() //默认就是get请求 可以不写
.build;
通过上述两步构造call对象 //
//addEncoded() 编码
new Thread(new Runnable() {
@Override
public void run() {
try {
Response response = call.execute();
Log.d(TAG, "run: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
OkHttp发送post请求
请求接口:https://api.github.com/markdown/raw
MIME大全:https://www.jianshu.com/p/9f5c2d3288c2
// 创建OkHttp客户端
OkHttpClient client = new OkHttpClient();
// 构建Mime类型
MediaType mediaType = MediaType.parse("text/plain");
// 构建请求体
RequestBody body = RequestBody.create(mediaType, "**123**");
// 构建HTTP请求
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.method("POST", body)
.build();
// 构建HTTP网络请求
Call call = client.newCall(request);
// 异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println(response.body().string());
}
});
POST方式提交String
这种方式与前面的区别就是在构造Request对象时,需要多构造一个RequestBody对象,用它来携带我们要提交的数据。在构造 RequestBody 需要指定MediaType,用于描述请求/响应 body 的内容类型,关于 MediaType 的更多信息可以查看https://tools.ietf.org/html/rfc2045,RequstBody的几种构造方式:
MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
String requestBody = "I am xts.";
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(mediaType, requestBody))
.build();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, response.protocol() + " " +response.code() + " " + response.message());
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG, headers.name(i) + ":" + headers.value(i));
}
Log.d(TAG, "onResponse: " + response.body().string());
}
});
POST提交文件
请求接口:https://api.github.com/markdown/raw
MIME大全:https://www.jianshu.com/p/9f5c2d3288c2
// 创建OkHttp客户端
OkHttpClient client = new OkHttpClient();
// 构建Mime类型
MediaType mediaType = MediaType.parse("text/plain");
// 构建请求体
RequestBody body = RequestBody.create(mediaType, "**123**");
// 构建HTTP请求
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.method("POST", body)
.build();
// 构建HTTP网络请求
Call call = client.newCall(request);
// 异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println(response.body().string());
}
});
// 提交字节数组
RequestBody.create(mediaType, bytes);
// 提交文件
RequestBody.create(mediaType, file);
POST方式提交表单
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new FormBody.Builder()
.add("search", "Jurassic Park")
.build();
Request request = new Request.Builder()
.url("https://en.wikipedia.org/w/index.php")
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, response.protocol() + " " +response.code() + " " + response.message());
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG, headers.name(i) + ":" + headers.value(i));
}
Log.d(TAG, "onResponse: " + response.body().string());
}
});
提交表单时,使用 RequestBody 的实现类FormBody来描述请求体,它可以携带一些经过编码的 key-value 请求体,键值对存储在下面两个集合中:
private final List<String> encodedNames;
private final List<String> encodedValues;