目录
一、简介
二、基本用法
1、添加依赖
2、使用
2.1 创建客户端对象
2.2 创建Request对象
2.3 生成网络请求对象
2.4 发起网络请求
2.5 示例
三、补充知识
3.1 RequestBody
3.2 Response
四、主要参考
OkHttp3是由square公司负责日常维护的开源项目,GitHub地址:https://github.com/square/okhttp ;
其中 3.14.x版本及以前的版本,均采用Java语言编写,4.0.0以后的采用kotlin语言编写;
本系列文章中源码均引用自3.14.x版本;
经过市场考验,公认为Android中最好用的网络开源框架,在日常开发中基本上完全取代了Google官方推荐的UrlConnection;
implementation 'com.squareup.okhttp3:okhttp:3.14.0'
implementation 'com.squareup.okio:okio:1.15.0'
OkHttpClient okHttpClient = new OkHttpClient(); // 创建OkHttpClient对象
(1)默认采用GET请求
Request request = new Request.Builder()
.url("your.interface?param_one=\"\"¶m_two=\"\"") // 接口地址
.build(); // 创建Request对象
(2) 采用POST请求
/**
先创建RequestBody,再调用Request的post方法
*/
/** 以FormBody为例 FormBody为RequestBody的子类 */
FormBody.Builder formBody = new FormBody.Builder(); // 创建FormBody
formBody.add("key","value"); // 传递键值对参数,即时组装
Request request = new Request.Builder() // 创建Request对象
.url("your_interface")
.post(formBody.build()) // 传递RequestBody对象
.build();
RealCall realCall = okHttpClient.newCall(request);
(1)同步请求
/**
* 须新开一个子线程执行RealCall.execute();
* 以下为一个 (GET + 同步) 的网络请求示例
*/
new Thread(new Runnable() {
@Override
public void run() {
try {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("your_interface")
.build();
Response response = null;
RealCall realCall = OkHttpClient.newCall(request);
response = realCall.execute(); // 得到Response 对象
if (response.isSuccessful()) {
// 拿到返回结果
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
(2)异步请求
/**
* realCall直接执行enqueue方法
* enqueue()自动在子线程中异步执行网络请求
*/
realCall.enqueue(new Callback{
@Override
public void onResponse(Call call, Response response) throws IOException{
if(response.isSuccessful()){
// 拿到返回结果,在子线程中执行
}
}
@Override
public void onFailure(Call call, IOException e){
// 异常处理
}
});
/** POST + 异步 */
// 创建OkHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
// 创建Request对象
FormBody.Builder formBody = new FormBody.Builder();
formBody.add("key","value");
Request request = new Request.Builder()
.url("your_interface")
.post(formBody.build())
.build();
// 发起异步网络请求
okHttpClient.newCall(request).enqueue(new Callback{
@Override
public void onResponse(Call call, Response response) throws IOException{
if(response.isSuccessful()){
// 拿到返回结果,在子线程中执行
}
}
@Override
public void onFailure(Call call, IOException e){
// 异常处理
}
});
对于POST请求,须想post方法传参RequestBody实例,根据不同的需求,有以下几种常见的实现方式:
(1)FormBody
表单类实例,适合传输键值对参数:
FormBody.Builder formBody = new FormBody.Builder();
formBody.add("key","value");
RequestBody requestBody = formBody.build();
(2) JSON格式对象或者File对象
1)对于json格式数据
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
String json = "{\"key_one\":\"value_one\",\"key_two\":\"value_two\"}";
RequestBody requestBody = RequestBody.create(josn, JSON);
2) 对于File类型数据
MediaType fileType = MediaType.parse("File/*");
File file = new File("your_file_path");
RequestBody requestBody = RequestBody.create(fileType , file);
3) MultipartBody
同时传递键值对参数与File类型参数
// 生成File类型的RequestBody
MediaType fileType = MediaType.parse("File/*");
File file = new File("your_file_path");
RequestBody requestBody = RequestBody.create(fileType , file);
// 生成MultipartBody
MultipartBody multipartBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("key_one", "value_one")
.addFormDataPart("key_two", "value_two")
.addFormDataPart("file", file.getName(), requestBody)
.build();
// 将MultipartBody传入post方法
Request request = new Request.Builder()
.url(”your_interface“)
.post(multipartBody)
.build();
4)自定义RequestBody
// 将自定义的requestBody实例直接传入post方法
// 可以传输流
RequestBody requestBody = new RequestBody() {
@Override
public MediaType contentType() {
return null;
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
// 重写writeTo方法
FileInputStream fileInputStream = new FileInputStream(new File("file_name"));
byte[] buffer = new byte[1024*8];
if(fileInputStream.read(buffer) != -1){
sink.write(buffer);
}
}
};
注意事项:
1、Response.code是http响应行中的code,如果访问成功则返回200.这个不是服务器设置的,而是http协议中自带的。res中的code才是服务器设置的。注意二者的区别。
2、response.body().string()本质是输入流的读操作,所以它还是网络请求的一部分,所以这行代码必须放在子线程。
3、response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。原因是:response.body().string()的本质是输入流的读操作,必须有服务器的输出流的写操作时客户端的读操作才能得到数据。而服务器的写操作只执行一次,所以客户端的读操作也只能执行一次,第二次将返回null。
参考链接(1):https://github.com/square/okhttp
参考链接(2):https://blog.csdn.net/qq_17470165/article/details/80543537
参考链接(3):https://blog.csdn.net/suyimin2010/article/details/80196443