okhttp源码系列-执行一次网络请求

带着目的阅读源码,okhttp如何执行一次网络请求呢?
本文通过samples.guide模块中的GetExample作为切入口。

入口

GetExample代码如下

class GetExample {

  val client: OkHttpClient = OkHttpClient() // 创建okhttp客户端

  fun run(url: String): String? {
    val request: Request = Request.Builder() // 创建请求
        .url(url)
        .addHeader("User-Agent", "OkHttp Example")
        .build() // 通过链式+build模式创建一个网络请求
    return runCatching {
      client.newCall(request).execute().use { response -> // 同步获取网络响应
        if (!response.isSuccessful) {
          null
        } else {
          response.body?.string()
        }
      } 
    }.getOrNull()
  }
}

从上述代码可知执行一次网络请求需要如下步骤:

  • step 1:创建okhttp客户端client
val client: OkHttpClient = OkHttpClient() // 创建okhttp客户端

  • step 2:创建网络请求并配置必要参数
val request: Request = Request.Builder() // 创建请求
    .url(url)
    .addHeader("User-Agent", "OkHttp Example")
    .build() // 通过链式+build模式创建一个网络请求

  • step 3:执行网络请求并获取网络返回
return runCatching {
  client.newCall(request).execute().use { response -> // 同步获取网络响应
    if (!response.isSuccessful) {
      null
    } else {
      response.body?.string()
    }
  }
}.getOrNull()

看上去是不是很简单,复杂的网络请求只需要三步即可完成,接下来我们带着问题逐步分析。

什么是okhttp客户端

OkHttp用途

第一步中创建了OkHttpClient对象,注释中对其的定义为:

Factory for calls, which can be used to send HTTP requests and read their responses.

用于生成Call的工厂,Call可以发送并接收HTTP请求。Call是一个接口,代表一个可以执行的HTTP请求,如下:

interface Call : Cloneable {
  fun request(): Request

  @Throws(IOException::class)
  fun execute(): Response

  fun enqueue(responseCallback: Callback)

  fun isExecuted(): Boolean

  fun isCanceled(): Boolean

  fun timeout(): Timeout

  public override fun clone(): Call

  fun interface Factory {
    fun newCall(request: Request): Call
  }
}

OkHttp的声明如下,除了可生成Call之外,还可生成一个WebSocket对象。

open class OkHttpClient internal constructor(
  builder: Builder
) : Cloneable, Call.Factory, WebSocket.Factory

WebSocket是一个WebSocket协议的操作接口,可利用它发送基于WebSocket协议的消息,WebSocket协议是基于TCP协议的可全双工通信的应用层网络协议,WebSocket接口如下:

interface WebSocket {
  fun request(): Request

  fun queueSize(): Long

  fun send(text: String): Boolean

  fun send(bytes: ByteString): Boolean

  fun close(code: Int, reason: String?): Boolean

  fun cancel()

  fun interface Factory {
    fun newWebSocket(request: Request, listener: WebSocketListener): WebSocket
  }
}

总结一下:OkHttpClient主要用途是生成Call对象(处理HTTP请求),生成WebSocket对象(处理WebSocket请求)

OkHttpClient属性

OkHttpClient基于Builder建造者模式,可通过链式结构清晰地设置网络配置,具体的配置项及其相应功能如下:

属性功能
dispatcher调度器,设置执行异步请求的策略。
connectionPool设置可回收复用的HTTP/HTTPS的连接池,相同地址的HTTP请求可共享一个连接。
interceptors一个可修改的拦截器列表,该列表作用于建立连接之前到选择响应源的区间。
networkInterceptors一个可修改的网络拦截器列表,该列表作用于单个请求发起到响应的区间。
eventListenerFactory可监听到该客户端网络调用中各个阶段的情况
retryOnConnectionFailure设置此客户端在遇到连接问题时是否重试,默认为true,在一些特定情况下重试
authenticator当网络返回出现授权问题时,设置授权并重试。
followRedirects设置是否重定向。
followSslRedirects设置是否允许HTTP和HTTPS协议间的重定向,优先满足followRedirects。
CookieJar设置Cookie的保存和读取机制,默认是没有Cookie处理的。
cache设置网络响应缓存,可在无网环境时读取缓存数据。
dns设置DNS服务,用于查找host于ip地址的映射。
proxy设置代理,优先级高于proxySelector。
proxySelector设置proxy选择器,可根据不同的url设置不同的选择器,当[proxy]设置为null时可用,类似PAC和全局代理。有时可通过ProxySelector防止抓包,绕过代理
proxyAuthenticator设置代理服务器的授权,而authenticator是设置原始服务器的授权。
socketFactory用于创建连接的sockets对象。
sslSocketFactory用于创建HTPPS连接的SSLSocket对象。
x509TrustManagerOrNullX509TrustManager主要用于校验HTTPS连接中服务端的证书,一般情况下无需设置,除非使用自签名证书或者不校验。
connectionSpecs主要用于指定HTTPS连接中可支持的TLS版本和密码套件。
protocols设置请求协议。
hostnameVerifier在握手期间,主要用于校验服务器的主机名是否与证书中的主机名相符,判断该连接是否有效。
certificatePinner通过设置合法的公钥,验证服务端证书的合法性,可以将你信任的服务器证书或公钥的散列值配置到你的客户端上,只有当服务器提供的证书或公钥的散列值与客户端配置的相匹配时,才认为这个连接是安全的。称作公钥锁定或证书固定
certificateChainCleaner用于移除不匹配的TSL链接并获取受信任的证书。
callTimeout设置一次完整请求(dns解析、连接、写入request、服务端处理、获取response;包括重定向和网络重试)的超时时间。
connectTimeout设置tcp连接(和target的tcp连接)的超时时间。
readTimeout设置服务器开始发送响应数据+客户端接收完响应数据的超时时间。
writeTimeout设置客户端开始发送请求数据+服务端接收完请求数据的超时时间。
pingInterval设置连续两次自动ping之间的时间间隔,使用此参数自动发送ping帧,直到连接失败或关闭。这将使连接保持活动状态,并可以检测到连接失败,在适用于长连接的场景。
minWebSocketMessageToCompress设置WebSocket消息需要压缩的最小大小,如果设置为1024,则WebSocket消息大于1024bytes后需要压缩,否则不压缩。
routeDatabaseOkHttp 的一个内部机制用于追踪和管理 HTTP 连接的路由信息,无法直接设置,可以通过connectionPool() 方法获取到连接池,并通过连接池来看到具体的路由信息

什么是Request请求

Request用途

Request为一个HTTP请求,其包含了urlmethodheadersbody等网络所需配置。

总结

本章首先介绍如何用okhttp发送一个网络请求,然后分析OkhttpClient和Request的组成元素,后续看看okhttp是如何将请求发送出去的。

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓(文末还有ChatGPT机器人小福利哦,大家千万不要错过)

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
图片

  • 24
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值