前言
OkHttp是目前使用最广泛的移动端网络底层库。在Volley、Retrofit等知名上层网络库中,都可以看到它的身影。即使在高版本的Android系统中的URLConnection中也可以看到它的身影。�
因为,各大网络库对OkHttp进行了封装。我们虽然使用方便,却不免失去了一定的灵活性。如果OkHttp拥有的功能,上层库却没有封装,我们在使用时,就会比较麻烦。因此,我们在这里尝试直接使用OkHttp,看看未经封装的OkHttp如何使用。
Request
OkHttp将请求封装在了Request类中。我们大致看看Request的成员:
public final class Request{
private final HttpUrl url;
private final String method;
private final Headers headers;
private final RequestBody body;
private final Object tag;
}
其中HttpUrl
类代表请求地址, String method
代表请求方法, Headers
代表请求头, RequestBody
代表请求体. Object tag
是用来取消http请求的标志, 这个我们先不管.
我们在使用OkHttp时,我们可以用Request提供的Builder生成我们想要的Request。
final Request request = new Request.Builder().url("https://github.com/").build();
完成Request的创建后,我们可以调用:
final Request request = new Request.Builder().url("https://github.com/").build();
Response response = client.newCall(request).execute();
从Request
被调用的方式,我们可以发现,这是一个同步网络请求。请求完成后,会直接返回Response
给我们。下面,我们就来看看Response
的结构。
Response
public final class Response{
private final Request request;
private final Protocol protocol;
private final int code;
private final String message;
private final HandShake handShake;
private final Headers headers;
private final ResponseBody body;
private Response networkResponse;
private Response cacheResponse;
private final Response priorResponse;
}
可以看到Response类里面有Protocol
代表请求协议, int code
代表响应码, String message
代表描述信息, Headers
代表响应头, ResponseBody
代表响应体. 当然除此之外, 还有Request
代表持有的请求, Handshake
代表SSL/TLS握手协议验证时的信息, 这些额外信息我们暂时不问.
介绍完Request
和Response
两个重要的类,下面我们可看看,OkHttp的各种请求的调用方法。
GET请求
同步GET
同步GET的意思是一直等待http请求, 直到返回了响应. 在这之间会阻塞进程, 所以通过get不能在Android的主线程中执行, 否则会报错。
private final OkHttpClient client = new OkHttpClient();
public void run() throw Exception{
Request request = new Request.Builder()
.url("https://github.com/")
.build();
Response response = client.newCall(request).execute();
}
异步GET
异步GET的意思是OkHttp会帮我们另外开启后台线程发送http请求,开启后台线程后,不再阻碍当前线程的执行。当http请求完成后,会以回调的方式,将请求结果返回到当前线程。
private final OkHttpClient client = new OkHttpClient();
public void run() throw Exception{
Request request = new Request.Builder()
.url("https://github.com/")
.build();
Response response = client.newCall(request).enqueue(new Callback(){
@Override
public void onResponse(Response response) throw IOException{
}
@Override
public void onFailure(Request request , Throwable throwable){
}
});
}
POST请求
在上面的GET请求的介绍中,我们已经分别介绍了同步请求和异常请求。在POST请求的介绍中,我们不再以同步和异步进行分类,只介绍同步情况,而把精力集中在,POST上传的内容形式的分类上。
POST提交String
private final OkHttpClient client = new OkHttpClient();
public void run() throw Exception{
String uploadInfo = "Need to Upload!";
Request request = new Request.Builder()
.url("https://github.com/")
.post(RequestBody.create("text/x-markdown; charset=utf-8" , uploadInfo))
.build();
Response response = client.newCall(request).execute();
}
POST提交文件
private final OkHttpClient client = new OkHttpClient();
public void run() throw Exception{
File file = new File("README.md");
Request request = new Request.Builder()
.url("https://github.com/")
.post(RequestBody.create("text/x-markdown; charset=utf-8" , file))
.build();
Response response = client.newCall(request).execute();
}
POST提交表单
private final OkHttpClient client = new OkHttpClient();
public void run() throw Exception{
RequestBody formBody = new formBody.Builder()
.add("user" , "oldFrog")
.build();
Request request = new Request.Builder()
.url("https://github.com/")
.post(formBody)
.build();
Response response = client.newCall(request).execute();
}
POST提交分块请求
private final OkHttpClient client = new OkHttpClient();
public void run() throw Exception{
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("user" , "oldFrog")
.addFormDataPart("image" , "logo.png" , RequestBody.create(MEDIA_TYPE_PNG, new File("local_logo.png")))
.build();
Request request = new Request.Builder()
.url("https://github.com/")
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
}
POST提交Stream
private static final MediaType MEDIA_TYPE_PLAINTEXT = MediaType
.parse("text/plain; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
@Test
public void testPostStream() throws Exception {
RequestBody requestBody = new RequestBody() {
@Override
public MediaType contentType() {
return MEDIA_TYPE_PLAINTEXT;
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
File file = new File("src/test/resources/Lorem Ipsum.txt");
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
sink.writeUtf8(line);
}
}
}
};
Request request = new Request.Builder()
.url("http://httpbin.org/post")
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
}
至此,就介绍了okhttp的基本使用。后面会开始分析okhttp的源码,以深入其进阶使用。
如有问题,欢迎指正。