OkHttp是一个Java和Android的HTTP和HTTP/2的客户端,负责发送HTTP请求以及接受HTTP响应。

一、使用OkHttp

OkHttp发送请求后,可以通过同步或异步地方式获取响应。下面就同步和异步两种方式进行介绍。

1.1、同步方式

发送请求后,就会进入阻塞状态,知道收到响应。下面看一个下载百度首页的例子:

 
  1. OkHttpClient client = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
  2. Request request = new Request.Builder().url("http://www.baidu.com")
  3. .get().build();
  4. Call call = client.newCall(request);
  5. try {
  6. Response response = call.execute();
  7. System.out.println(response.body().string());
  8. } catch (IOException e) {
  9. e.printStackTrace();
  10. }

  

上面的代码先创建OkHttpClient和Request对象,两者均使用了Builder模式;然后将Request封装成Call对象,然后调用Call的execute()同步发送请求,最后打印响应。

1.2、异步方式

异步方式是在回调中处理响应的,同样看下载百度首页的例子:

  1. OkHttpClient client = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
  2. Request request = new Request.Builder().url("http://www.baidu.com")
  3. .get().build();
  4. Call call = client.newCall(request);
  5. call.enqueue(new Callback() {
  6. @Override
  7. public void onFailure(Call call, IOException e) {
  8. System.out.println("Fail");
  9. }
  10.  
  11. @Override
  12. public void onResponse(Call call, Response response) throws IOException {
  13.  
  14. System.out.println(response.body().string());
  15.  
  16. }
  17. });

  

同样是创建OkHttpClient、Request和Call,只是调用了enqueue方法并在回调中处理响应。 
上面介绍了同步、异步获取请求的步骤,都是比较简单的。

1.3、Request、Response、Call

上面的代码中涉及到几个常用的类:Request、Response和Call。下面分别介绍: 
Request 
每一个HTTP请求包含一个URL、一个方法(GET或POST或其他)、一些HTTP头。请求还可能包含一个特定内容类型的数据类的主体部分。 
Response 
响应是对请求的回复,包含状态码、HTTP头和主体部分。 
重写请求 
当将Request提交给OkHttp后,出于正确性和效率的考虑,OkHttp在传输请求之前会重写请求。 
OkHttp可能会在请求中添加缺少的请求头,包括”Content-Length”,”Transfer-Encoding”,”User-Agent”,”HOST”,”Connection”和”Content-Type”等。 
有些请求可能有缓存的响应。当缓存响应过时时,OkHttp可以做一个额外的GET请求获取最新的响应。这要求”If-Modified-Since”和”If-None-Match”头被添加。 
重写响应 
如果使用了透明压缩,OkHttp会丢弃”Content-Encoding”和”Content-Length”头,因为和解压后的响应主体不匹配。 
如果一个额外的GET请求成功了,那么网络和缓存中的响应将会合并。 
请求重定向 
当请求的URL移动了,web服务器会返回一个302的状态码并指明文件的新地址。OkHttp将会重定向获取最终的响应。 
请求重试 
有时连接会失败,那么OkHttp会重试别的路由。 
Call 
当重写、重定向等时,一个请求可能会产生多个请求和响应。OkHttp使用Call抽象出一个满足请求的模型,尽管中间可能会有多个请求或响应。执行Call有两种方式,同步或异步,这在上面已经介绍过了。 
Call可以在任何线程被取消。

二、拦截器

拦截器是一个监视、重写、重试请求的强有力机

从图中可以看出,拦截器分为应用拦截器和网络拦截器两种。应用拦截器是在发送请求之前和获取到响应之后进行操作的,网络拦截器是在进行网络获取前进行操作的。

2.1、应用拦截器

下面定义一个应用拦截器,用于在请求发送前打印URL以及接受到响应后打印内容。

  1. public class LogInterceptor implements Interceptor {
  2.  
  3. @Override
  4. public Response intercept(Chain chain) throws IOException {
  5.  
  6. Request request = chain.request();
  7.  
  8. System.out.println(request.toString());
  9.  
  10. Response response = chain.proceed(request);
  11.  
  12. System.out.println(response);
  13.  
  14. return response;
  15. }
  16. }

  上面的代码中,LogInterceptor实现了Interceptor接口。首先从chain中得到请求,然后打印请求;然后调用proceed方法处理请求得到响应,然后打印响应。调用代码如下:

  1. OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new LogInterceptor()).build();
  2. Request request = new Request.Builder().url("http://www.baidu.com")
  3. .get().build();
  4. Call call = okHttpClient.newCall(request);
  5. try {
  6. call.execute();
  7. } catch (IOException e) {
  8. e.printStackTrace();
  9. }

  

可以看到通过调用addInterceptor方法添加应用拦截器。

2.2、网络拦截器

网络拦截器的使用和应用拦截器类似,只是调用OkHttpClient的addNetworkInterceptor方法即可。

  1. OkHttpClient okHttpClient = new OkHttpClient.Builder().addNetworkInterceptor(new LogInterceptor()).build();
  2. Request request = new Request.Builder().url("http://www.taobao.com")
  3. .get().build();
  4. Call call = okHttpClient.newCall(request);
  5. try {
  6. call.execute();
  7. } catch (IOException e) {
  8. e.printStackTrace();
  9. }

  下面是运行结果:

  1. Request{method=GET, url=http://www.taobao.com/, tag=Request{method=GET, url=http://www.taobao.com/, tag=null}}
  2. Response{protocol=http/1.1, code=302, message=Found, url=http://www.taobao.com/}
  3. Request{method=GET, url=https://www.taobao.com/, tag=Request{method=GET, url=http://www.taobao.com/, tag=null}}
  4. Response{protocol=http/1.1, code=200, message=OK, url=https://www.taobao.com/}

  

可以发现,拦截器运行了两次。一次是初始请求”http://www.taobao.com“,一次是请求重定向”https://www.taobao.com“。

2.3、应用拦截器和网络拦截器的比较

每个拦截器由它各自的优势。 
应用拦截器 
- 不需要考虑中间状态的响应,比如重定向或者重试。 
- 只会被调用一次,甚至于HTTP响应保存在缓存中。 
- 观察应用程序的原意。 
- 允许短路,可以不调用Chain.proceed()方法 
- 允许重试和发送多条请求,调用Chain.proceed()方法 
网络拦截器 
- 可以操作中间状态的响应,比如重定向和重试 
- 不调用缓存的响应 
- 可以观察整个网络上传输的数据 
- 获得携带请求的Connection

2.4、重写请求

拦截器可以添加、移除或者替换请求的头信息,也可以改变传输的主体部分。下面的一个拦截器对请求主体进行Gzip压缩。

  1. final class GzipRequestInterceptor implements Interceptor {
  2. @Override public Response intercept(Interceptor.Chain chain) throws IOException {
  3. Request originalRequest = chain.request();
  4. if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
  5. return chain.proceed(originalRequest);
  6. }
  7.  
  8. Request compressedRequest = originalRequest.newBuilder()
  9. .header("Content-Encoding", "gzip")
  10. .method(originalRequest.method(), gzip(originalRequest.body()))
  11. .build();
  12. return chain.proceed(compressedRequest);
  13. }
  14.  
  15. private RequestBody gzip(final RequestBody body) {
  16. return new RequestBody() {
  17. @Override public MediaType contentType() {
  18. return body.contentType();
  19. }
  20.  
  21. @Override public long contentLength() {
  22. return -1; // We don't know the compressed length in advance!
  23. }
  24.  
  25. @Override public void writeTo(BufferedSink sink) throws IOException {
  26. BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
  27. body.writeTo(gzipSink);
  28. gzipSink.close();
  29. }
  30. };
  31. }
  32. }

  

2.5、重写响应

同样地,拦截器可以重写响应的头部以及主体部分。但是

  1. /** Dangerous interceptor that rewrites the server's cache-control header. */
  2. private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
  3. @Override public Response intercept(Interceptor.Chain chain) throws IOException {
  4. Response originalResponse = chain.proceed(chain.request());
  5. return originalResponse.newBuilder()
  6. .header("Cache-Control", "max-age=60")
  7. .build();
  8. }
  9. };

  

三、总结

本篇文章主要介绍了OkHttp进行GET的同步、异步请求,对于HTTP其他方法,比如POST等都是可以进行的,这儿就不过多介绍了,想了解的朋友可以到OkHttp Github地址查看.

OkHttp 同步异步操作的更多相关文章

  1. Okhttp同步请求源码分析

    进阶android,OKhttp源码分析——同步请求的源码分析 OKhttp是我们经常用到的框架,作为开发者们,我们不单单要学会灵活使用,还要知道他的源码是如何设计的. 今天我们来分析一下OKhttp ...

  2. 关于OkHttp同步请求的小错误

    今天进行OkHttp的同步请求 写的都是按照官方的去写的 但是返回的东西却不是我想要的 原因是我直接拿到Response后,直接Response.toString,想要拿到返回值 但是这样是错误的,正 ...

  3. okhttp同步请求流程和源码分析

    在上一次[http://www.cnblogs.com/webor2006/p/8022808.html]中已经对okhttp的同步与异步请求的基本使用有了一了初步了解,这次来从源码的角度来分析一下同 ...

  4. Android okHttp网络请求之Get/Post请求

    前言: 之前项目中一直使用的Xutils开源框架,从xutils 2.1.5版本使用到最近的xutils 3.0,使用起来也是蛮方便的,只不过最近想着完善一下app中使用的开源框架,由于Xutils里 ...

  5. 网络请求三方库——OkHttp

    我们知道在Android开发中是可以直接使用现成的API进行网络请求的,就是使用 HttpClient 和 HttpURLConnention ,而Android 4.4 之后 HttpClient  ...

  6. okhttp 基本介绍

    资料汇总 官网:http://square.github.io/okhttp/ 文档:https://github.com/square/okhttp/wiki GitHub:https://gith ...

  7. 《Windows驱动开发技术详解》之IRP的同步

    应用程序对设备的同步异步操作: 大部分IRP都是由应用程序的Win32 API函数发起的.这些Win32 API本身就支持同步和异步操作.例如,ReadFile.WriteFile和DeviceIoC ...

  8. Android 开发 框架系列 OkHttp使用详解

    简介 okhttp是一个第三方类库,用于android中请求网络.这是一个开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso和LeakCanary) . ...

  9. Java同步、异步区别

    一.概念: 1.同步:所有的操作都做完,才返回给用户.这样用户在线等待的时间太长,给用户一种卡死了的感觉(就是系统迁移中,点击了迁移,界面就不动了,但是程序还在执行,卡死了的感觉).这种情况下,用户不 ...

随机推荐

  1. web.html

    在“Web页”节点下,展开WEB-INF节点,然后双击web.xml文件进行查看. web.xml文件包含Facelets应用程序所需的几个元素.使用NetBeans IDE创建应用程序时,将自动创建 ...

  2. 关于ajax跨域的一些解决方案

    1.JSONP方式解决跨域问题 jsonp解决跨域问题是一个比较古老的方案(实际中不推荐使用),当然,在实际项目中如果要使用JSONP,一般会使用JQ等对JSONP进行了封装的类库来进行ajax请求 ...

  3. Windows 下 安装 laravel(一些小笔记)

    首先 安装完composer       下载地址    https://getcomposer.org/ 在  cmd  进入到  自己的项目访问目录 然后  输入命令:composer creat ...

  4. 4.python字符串格式化

    格式化字符串时,Python使用一个字符串作为模板.模板中有格式符,这些格式符为真实值预留位置,并说明真实数值应该呈现的格式.Python用一个tuple将多个值传递给模板,每个值对应一个格式符.py ...

  5. 同时开始了SQL。。。

    SQL LIMIT OFFSET 和 LIMIT code1: SELECT id, name, score FROM table ORDER BY score DESC LIMIT OFFSET 4 ...

  6. js 在线引用

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta ht ...

  7. zombodb 索引管理

    zombodb 支持标准的index 管理(create .alter.drop) 创建索引 CREATE INDEX index_name ON table_name USING zombodb ( ...

  8. bootstrap 模态框事件

    事件 描述 实例 show.bs.modal 在调用 show 方法后触发. $('#identifier').on('show.bs.modal', function () { // 执行一些动作. ...

  9. 1.2.2 Excel中手机号或身份证号批量加密星号

    在对应的单元格中我们输入公式: =LEFT(C4,3)&"****"&RIGHT(C4,4)或=MID(C4,1,3)&"****"&a ...

  10. Linux之文件(目录)默认权限、特殊权限与隐藏权限

    文件默认权限 从Linux之用户组.文件权限详解了解到文件与目录的基本权限管理,文件在创建时如果不指定具体的权限,那么系统会给它分配一个默认的权限,这个默认权限就是umask. vbird@Ubunt ...