当前位置:网站首页 > 技术博客 > 正文

okhttp配置



欢迎关注公众号:胡飞洋 预计okhttp系列有4篇,使用方法、流程分析、缓存和连接池、使用扩展及封装。 这是第一篇,按照惯例,就介绍基本的使用方法,比较简单。 好了,闲话少叙,开始! 所需 预备知识: HTTP协议详解 HTTP请求报文和响应报文

现在Android中的网络请求框架,基本都是okhttp和Retrofit一统天下,而Retrofit又是以okhttp为基础,所以系统学习okhttp的使用和原理就很有必要了。

okhttp是由square公司开发,Android中公认最好用的网络请求框架,在接口封装上做的简单易用,GitHub地址:https://github.com/square/okhttp。

它有以下默认特性:

当网络出现问题的时候OkHttp 会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP。

gradle引入依赖即可。

3.14.x版本及以前的版本,采用Java语言编写,4.0.0以后采用kotlin语言;本系列文章中源码引自3.14.x版本,以Java语言讲解。

其中Okio库 是对Java.io和java.nio的补充,以便能够更加方便,快速的访问、存储和处理你的数据。OkHttp的底层使用该库作为支持。

另外,别忘了申请网络请求权限,如果还使用网络请求的缓存功能,那么还要申请读写外存的权限:

基本使用步骤如下

下面跟着具体使用实例,详细介绍。

以百度主页为例,进行Get请求:

首先,创建了OkHttpClient实例,接着用Request.Builder构建了Request实例并传入了百度主页的url,然后httpClient.newCall方法传入Request实例生成call,最后在子线程调用call.execute()执行请求获得结果response。

所以,使用OkHttp进行get请求,是比较简单的,只要在构建Request实例时更换url就可以了。

异步请求

有个问题,你可能注意到了,这里是放在子线程执行请求的,这是因为call.execute()是同步方法。想要在主线程直接使用而不用手动创建子线程可以嘛?当然可以,使用call.enqueue(callback)即可:

call.enqueue会异步执行,需要注意的是,两个回调方法onFailure、onResponse是执行在子线程的,所以如果想要执行UI操作,需要使用Handler切换到UI线程。

取消请求

每一个Call只能执行一次(原因会在下篇流程分析中说明)。如果想要取消正在执行的请求,可以使用call.cancel(),通常在离开页面时都要取消执行的请求的。

结果处理

请求回调的两个方法是指 传输层 的失败和成功。onFailure通常是connection连接失败或读写超时;onResponse是指,成功的从服务器获取到了结果,但是这个结果的响应码可能是404、500等,也可能就是200(response.code()的取值)。

如果response.code()是200,表示应用层请求成功了。此时我们可以获取Response的ResponseBody,这是响应体。从面看到,可以从ResponseBody获取string、byte[]、InputStream,这样就可以对结果进行很多操作了,比如UI上展示string(要用Handler切换到UI线程)、通过InputStream写入文件等等。

上面异步请求执行后 结果打印如下:

可见百度首页的get请求成功响应了。

2.2.1 post请求提交String、文件

post请求与get请求的区别 是 在构造Request对象时,需要多构造一个RequestBody对象,用它来携带我们要提交的数据,其他都是一样的。示例如下:

对比get请求,把构建Request时的get()改成post(body),并传入RequestBody实例。RequestBody实例是通过create方法创建,需要指定请求体内容类型、请求体内容。这里是传入了一个指定为markdown格式的文本。

结果打印如下:

请求成功并把请求体内容又返回来了。

传入RequestBody的 MediaType 还可以是其他类型,如客户端要给后台发送json字符串、发送一张图片,那么可以定义为:

MediaType更多类型信息可以查看 RFC 2045:https://tools.ietf.org/html/rfc2045。

2.2.2 post请求提交表单

构建RequestBody除了上面的方式,还有它的子类FormBody,FormBody用于提交表单键值对,这种能满足平常开发大部分的需求。

FormBody是通过FormBody.Builder用构建者模式创建,add键值对即可。它的contentType在内部已经指定了。

2.2.2 post请求提交复杂请求体

RequestBody另一个子类MultipartBody,用于post请求提交复杂类型的请求体。复杂请求体可以同时包含多种类型的的请求体数据。

上面介绍的 post请求 string、文件、表单,只有单一类型。考虑一种场景--注册场景,用户填写完姓名、电话,同时要上传头像图片,这时注册接口的请求体就需要 接受 表单键值对 以及文件了,那么前面讲的的post就无法满足了。那么就要用到MultipartBody了。 完整代码如下:

可见,在构建RequestBody时是使用MultipartBody.Builder构建了MultipartBody实例,通过addFormDataPart方法传入了姓名、电话的键值对,也通过addFormDataPart("touxiang", "00.png", fileBody)传入了头像图片,其中"touxiang"是key值, "00.png"是文件名,fileBody是要以上传的图片创建的RequestBody。 因为所有数据都是以键值对的表单形式提交,所以要设置setType(MultipartBody.FORM)。

请求抓包结果:

在这里插入图片描述 可见请求体重确实包含了姓名、电话、头像,并且注意到Content-Type值是 multipart/form-data。响应是200,说明请求成功了。

其他请求方式像put、header、delete,主要在构建Request时把get()或post()换成put()、header()、delete()就可以了,但一般在Android端很少用到。

先看几个问题:

这些问题,在OkHttp这里很简单。把OkHttpClient实例的创建,换成以下方式即可:

这里通过OkHttpClient.Builder通过构建者模式设置了连接、读取、写入的超时时长,用cache()方法传入了由缓存目录、缓存大小构成的Cache实例,这样就解决了前两个问题。

还注意到,使用addInterceptor()方法添加了Interceptor实例,且重写了intercept方法。Interceptor意为拦截器,intercept()方法会在开始执行请求时调用。其中chain.proceed(request)内部是真正请求的过程,是阻塞操作,执行完后会就会得到请求结果ResponseBody,所以chain.proceed(request)的前后取当前时间,那么就知道整个请求所耗费的时间。上面chain.proceed(request)的前后分别打印的日志和时间,这样第三个问题也解决了。

具体Interceptor是如何工作,会在下一篇流程分析中介绍。 另外,通常OkHttpClient实例是全局唯一的,这样这些基本配置就是统一,且内部维护的连接池也可以有效复用(会在下一篇流程分析中介绍)。

全局配置的有了,单个请求的也可以有一些单独的配置。

这个Request实例,

好了,okhttp的使用就讲这里了,总体还是比较简单的。下篇是okhttp的工作流程分析,敬请期待~

  • 上一篇: cpio文件解压
  • 下一篇: 移位指令的用途
  • 版权声明


    相关文章:

  • cpio文件解压2025-08-20 12:30:02
  • php文件管理系统2025-08-20 12:30:02
  • rbac权限管理设计五张表2025-08-20 12:30:02
  • 程序员入门课程2025-08-20 12:30:02
  • 密码学基础入门2025-08-20 12:30:02
  • 移位指令的用途2025-08-20 12:30:02
  • linux发行版大全2025-08-20 12:30:02
  • 指针数组指向二维数组2025-08-20 12:30:02
  • js开发环境搭建2025-08-20 12:30:02
  • sql编程思想2025-08-20 12:30:02