热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Android使用OkHttp进行网络同步异步操作

这篇文章主要为大家详细介绍了Android使用OkHttp进行网络同步异步操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

一、使用OkHttp

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

1.1、同步方式

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

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

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

1.2、异步方式

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

 OkHttpClient client = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
    Request request = new Request.Builder().url("http://www.baidu.com")
        .get().build();
    Call call = client.newCall(request);
    call.enqueue(new Callback() {
      @Override
      public void onFailure(Call call, IOException e) {
        System.out.println("Fail");
      }

      @Override
      public void onResponse(Call call, Response response) throws IOException {

        System.out.println(response.body().string());

      }
    });

同样是创建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以及接受到响应后打印内容。

public class LogInterceptor implements Interceptor {

  @Override
  public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    System.out.println(request.toString());
    Response respOnse= chain.proceed(request);
    System.out.println(response);
    return response;
  }
}

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

 OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new LogInterceptor()).build();
    Request request = new Request.Builder().url("http://www.baidu.com")
        .get().build();
    Call call = okHttpClient.newCall(request);
    try {
      call.execute();
    } catch (IOException e) {
      e.printStackTrace();
    }

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

2.2、网络拦截器

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

OkHttpClient okHttpClient = new OkHttpClient.Builder().addNetworkInterceptor(new LogInterceptor()).build();
    Request request = new Request.Builder().url("http://www.taobao.com")
        .get().build();
    Call call = okHttpClient.newCall(request);
    try {
      call.execute();
    } catch (IOException e) {
      e.printStackTrace();
    }

下面是运行结果:

Request{method=GET, url=http://www.taobao.com/, tag=Request{method=GET, url=http://www.taobao.com/, tag=null}}
Response{protocol=http/1.1, code=302, message=Found, url=http://www.taobao.com/}
Request{method=GET, url=https://www.taobao.com/, tag=Request{method=GET, url=http://www.taobao.com/, tag=null}}
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压缩。

final class GzipRequestInterceptor implements Interceptor {
 @Override public Response intercept(Interceptor.Chain chain) throws IOException {
  Request originalRequest = chain.request();
  if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
   return chain.proceed(originalRequest);
  }

  Request compressedRequest = originalRequest.newBuilder()
    .header("Content-Encoding", "gzip")
    .method(originalRequest.method(), gzip(originalRequest.body()))
    .build();
  return chain.proceed(compressedRequest);
 }

 private RequestBody gzip(final RequestBody body) {
  return new RequestBody() {
   @Override public MediaType contentType() {
    return body.contentType();
   }

   @Override public long contentLength() {
    return -1; // We don't know the compressed length in advance!
   }

   @Override public void writeTo(BufferedSink sink) throws IOException {
    BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
    body.writeTo(gzipSink);
    gzipSink.close();
   }
  };
 }
}

2.5、重写响应

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

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

三、总结

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 本文详细探讨了HTTP 500内部服务器错误的成因、解决方案及其在Web开发中的影响。通过对具体案例的分析,帮助读者理解并解决此类问题。 ... [详细]
  • 通过与阿里云的合作,牛客网成功解决了跨国视频面试中的网络卡顿问题,为求职者和面试官提供了更加流畅的沟通体验。 ... [详细]
  • 本文探讨了如何在 PHP 的 Eloquent ORM 中实现数据表之间的关联查询,并通过具体示例详细解释了如何将关联数据嵌入到查询结果中。这不仅提高了数据查询的效率,还简化了代码逻辑。 ... [详细]
  • 本文详细介绍了IBM DB2数据库在大型应用系统中的应用,强调其卓越的可扩展性和多环境支持能力。文章深入分析了DB2在数据利用性、完整性、安全性和恢复性方面的优势,并提供了优化建议以提升其在不同规模应用程序中的表现。 ... [详细]
  • 网络攻防实战:从HTTP到HTTPS的演变
    本文通过一系列日记记录了从发现漏洞到逐步加强安全措施的过程,探讨了如何应对网络攻击并最终实现全面的安全防护。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 在维护公司项目时,发现按下手机的某个物理按键后会激活相应的服务,并在屏幕上模拟点击特定坐标点。本文详细介绍了如何使用ADB Shell Input命令来模拟各种输入事件,包括滑动、按键和点击等。 ... [详细]
  • 百度服务再次遭遇技术问题,疑似DNS解析故障
    近日晚间,百度多项在线服务出现加载异常,包括移动端搜索在内的多个功能受到影响。初步迹象表明,问题可能与DNS服务器解析有关。 ... [详细]
  • 摘要:为了解决下载速度慢的问题,本文介绍了一种高效的下载方法,并提供了详细的步骤和工具推荐。通过使用百度网盘分享功能,可以显著提高文件传输效率。 ... [详细]
  • 本文将深入探讨PHP编程语言的基本概念,并解释PHP概念股的含义。通过详细解析,帮助读者理解PHP在Web开发和股票市场中的重要性。 ... [详细]
  • 本文介绍了一种有效的方法来检测硬盘上的视频文件是否损坏或存在缺帧问题。虽然一些常见的搜索引擎并未提供专门的工具,但通过使用FFmpeg等专业软件,可以全面验证各种视频格式的数据完整性,包括较为古老的AVI格式。 ... [详细]
  • 本次考试于2016年10月25日上午7:50至11:15举行,主要涉及数学专题,特别是斐波那契数列的性质及其在编程中的应用。本文将详细解析考试中的题目,并提供解题思路和代码实现。 ... [详细]
author-avatar
永欣慧娟766
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有