当前位置: 首页 > news >正文

Kotlin 中 OkHttp 使用及解析

build.gradle

dependencies {//OkHttpimplementation 'com.squareup.okhttp3:okhttp:4.9.0'
}

简单使用例子

            val okHttpClient = OkHttpClient.Builder().connectTimeout(Duration.ofSeconds(10)).readTimeout(Duration.ofSeconds(10)).writeTimeout(Duration.ofSeconds(10)).retryOnConnectionFailure(true).build()val request = Request.Builder().url(url).build()val call = okHttpClient.newCall(request)call.enqueue(object : Callback {override fun onFailure(call: Call, e: IOException) {Log.e("TAG", "onFailure:${e.message}")}override fun onResponse(call: Call, response: Response) {Log.d("TAG", "onResponse: ${response.body?.string()}")}})

1、通过 Builder 模式得到  okHttpClient ,OkHttpClient 包含了对网络请求的全局配置信息,包括链接超时时间、读写超时时间、链接失败重试等配置。

2、通过 Builder 模式得到 request ,Request 包含了本次网络请求的所有请求参数,包括 url、method、headers、body 等。

3、通过 newCall 方法得到 call,Call 就是用于发起请求,可用于执行 同步请求(execute)、异步请求(enqueue)、取消请求(cancel)等各种操作。

4、调用 enqueue 方法发起异步请求返回 response ,Response 就包含了此次网络请求的所有返回信息。

5、拿到 Response 对象的 body 并以字符串流的方式进行读取。

一、OkHttpClient

OkHttpClient 使用 Builder模式来完成初始化,其提供了很多配置参数,每个选项都有默认值。

  class Builder constructor() {internal var dispatcher: Dispatcher = Dispatcher()internal var connectionPool: ConnectionPool = ConnectionPool()internal val interceptors: MutableList<Interceptor> = mutableListOf()internal val networkInterceptors: MutableList<Interceptor> = mutableListOf()internal var eventListenerFactory: EventListener.Factory = EventListener.NONE.asFactory()internal var retryOnConnectionFailure = trueinternal var authenticator: Authenticator = Authenticator.NONEinternal var followRedirects = trueinternal var followSslRedirects = trueinternal var cookieJar: CookieJar = CookieJar.NO_COOKIESinternal var cache: Cache? = nullinternal var dns: Dns = Dns.SYSTEMinternal var proxy: Proxy? = nullinternal var proxySelector: ProxySelector? = nullinternal var proxyAuthenticator: Authenticator = Authenticator.NONEinternal var socketFactory: SocketFactory = SocketFactory.getDefault()internal var sslSocketFactoryOrNull: SSLSocketFactory? = nullinternal var x509TrustManagerOrNull: X509TrustManager? = nullinternal var connectionSpecs: List<ConnectionSpec> = DEFAULT_CONNECTION_SPECSinternal var protocols: List<Protocol> = DEFAULT_PROTOCOLSinternal var hostnameVerifier: HostnameVerifier = OkHostnameVerifierinternal var certificatePinner: CertificatePinner = CertificatePinner.DEFAULTinternal var certificateChainCleaner: CertificateChainCleaner? = nullinternal var callTimeout = 0internal var connectTimeout = 10_000internal var readTimeout = 10_000internal var writeTimeout = 10_000internal var pingInterval = 0internal var minWebSocketMessageToCompress = RealWebSocket.DEFAULT_MINIMUM_DEFLATE_SIZEinternal var routeDatabase: RouteDatabase? = null
}

二、Request 

Request 包含了网络请求时的所有请求参数,一共包含以下五个。

  open class Builder {internal var url: HttpUrl? = nullinternal var method: Stringinternal var headers: Headers.Builderinternal var body: RequestBody? = null/** A mutable map of tags, or an immutable empty map if we don't have any. */internal var tags: MutableMap<Class<*>, Any> = mutableMapOf()
}

三、Call 

当调用 okHttpClient.newCall(request)   时就会得到一个 call 对象。

  /** Prepares the [request] to be executed at some point in the future. */override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)

 call 是一个接口,我们可以将其看做是网络请求的启动器,可用于同步请求异步请求,但重复发起多次请求的话会抛出异常。

interface Call : Cloneable {/** Returns the original request that initiated this call. */fun request(): Request/*** Invokes the request immediately, and blocks until the response can be processed or is in error.** To avoid leaking resources callers should close the [Response] which in turn will close the* underlying [ResponseBody].** ```* // ensure the response (and underlying response body) is closed* try (Response response = client.newCall(request).execute()) {*   ...* }* ```** The caller may read the response body with the response's [Response.body] method. To avoid* leaking resources callers must [close the response body][ResponseBody] or the response.** Note that transport-layer success (receiving a HTTP response code, headers and body) does not* necessarily indicate application-layer success: `response` may still indicate an unhappy HTTP* response code like 404 or 500.** @throws IOException if the request could not be executed due to cancellation, a connectivity*     problem or timeout. Because networks can fail during an exchange, it is possible that the*     remote server accepted the request before the failure.* @throws IllegalStateException when the call has already been executed.*/@Throws(IOException::class)fun execute(): Response/*** Schedules the request to be executed at some point in the future.** The [dispatcher][OkHttpClient.dispatcher] defines when the request will run: usually* immediately unless there are several other requests currently being executed.** This client will later call back `responseCallback` with either an HTTP response or a failure* exception.** @throws IllegalStateException when the call has already been executed.*/fun enqueue(responseCallback: Callback)/** Cancels the request, if possible. Requests that are already complete cannot be canceled. */fun cancel()/*** Returns true if this call has been either [executed][execute] or [enqueued][enqueue]. It is an* error to execute a call more than once.*/fun isExecuted(): Booleanfun isCanceled(): Boolean/*** Returns a timeout that spans the entire call: resolving DNS, connecting, writing the request* body, server processing, and reading the response body. If the call requires redirects or* retries all must complete within one timeout period.** Configure the client's default timeout with [OkHttpClient.Builder.callTimeout].*/fun timeout(): Timeout/*** Create a new, identical call to this one which can be enqueued or executed even if this call* has already been.*/public override fun clone(): Callfun interface Factory {fun newCall(request: Request): Call}
}

 ReallCall 是 Call 接口的唯一实现类

当调用 execute 方法发起同步请求时,

1、判断是否重复请求。

2、时间记录。

3、将自身加入到 dispatcher 中,并在请求结束时从 dispatcher 中移除自身。

4、通过 getResponseWithInterceptorChain 方法得到  response 对象。

override fun execute(): Response {check(executed.compareAndSet(false, true)) { "Already Executed" }timeout.enter()callStart()try {client.dispatcher.executed(this)return getResponseWithInterceptorChain()} finally {client.dispatcher.finished(this)}}

四、Dispatcher 

Dispatcher 是一个调度器,用于对全局的网络请求进行缓存调度,其包含一下几个成员变量。

var maxRequests = 64var maxRequestsPerHost = 5/** Ready async calls in the order they'll be run. */
private val readyAsyncCalls = ArrayDeque<AsyncCall>()/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
private val runningAsyncCalls = ArrayDeque<AsyncCall>()/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
private val runningSyncCalls = ArrayDeque<RealCall>()

1、maxRequests  同一时间允许并发执行网络请求的最大线程数。

2、maxRequestsPerHost  同一个 host 下的最大同时请求数。

3、readyAsyncCalls  保存当前等待执行的异步任务

4、runningAsyncCalls  保存当前正在执行的异步任务。

5、runningSyncCalls  保存等钱正在执行的同步任务。 

五、getResponseWithInterceptorChain

其主要逻辑就是通过拦截器来完成整个网络请求过程。

@Throws(IOException::class)internal fun getResponseWithInterceptorChain(): Response {// Build a full stack of interceptors.val interceptors = mutableListOf<Interceptor>()interceptors += client.interceptorsinterceptors += RetryAndFollowUpInterceptor(client)interceptors += BridgeInterceptor(client.cookieJar)interceptors += CacheInterceptor(client.cache)interceptors += ConnectInterceptorif (!forWebSocket) {interceptors += client.networkInterceptors}interceptors += CallServerInterceptor(forWebSocket)val chain = RealInterceptorChain(call = this,interceptors = interceptors,index = 0,exchange = null,request = originalRequest,connectTimeoutMillis = client.connectTimeoutMillis,readTimeoutMillis = client.readTimeoutMillis,writeTimeoutMillis = client.writeTimeoutMillis)var calledNoMoreExchanges = falsetry {val response = chain.proceed(originalRequest)if (isCanceled()) {response.closeQuietly()throw IOException("Canceled")}return response} catch (e: IOException) {calledNoMoreExchanges = truethrow noMoreExchanges(e) as Throwable} finally {if (!calledNoMoreExchanges) {noMoreExchanges(null)}}}

六、interceptor 

interceptor 多个拦截器增加串行调用逻辑

package com.gxxclass Request
class Responseinterface Chain {fun request(): Requestfun proceed(request: Request): Response
}interface Interceptor {fun intercept(chain: Chain): Response
}class RealInterceptorChain(private val request: Request,private val interceptors: List<Interceptor>,private val index: Int
) : Chain {private fun copy(index: Int): RealInterceptorChain {return RealInterceptorChain(request, interceptors, index)}override fun request(): Request {return request}override fun proceed(request: Request): Response {val next = copy(index + 1)val interceptor = interceptors[index]return interceptor.intercept(next)}
}class LogInterceptor : Interceptor {override fun intercept(chain: Chain): Response {val request = chain.request()println("LogInterceptor -- getRequest")val response = chain.proceed(request)println("LogInterceptor ---- getResponse")return response}
}class HeaderInterceptor : Interceptor {override fun intercept(chain: Chain): Response {val request = chain.request()println("HeaderInterceptor -- getRequest")val response = chain.proceed(request)println("HeaderInterceptor ---- getResponse")return response}
}class CallServerInterceptor : Interceptor {override fun intercept(chain: Chain): Response {val request = chain.request()println("CallServerInterceptor -- getRequest")val response = Response()println("CallServerInterceptor ---- getResponse")return response}
}fun main() {val interceptorList = mutableListOf<Interceptor>()interceptorList.add(LogInterceptor())interceptorList.add(HeaderInterceptor())interceptorList.add(CallServerInterceptor())val request = Request()val realInterceptorChain = RealInterceptorChain(request, interceptorList, 0)val response = realInterceptorChain.proceed(request)println("main response")
}/*
fun main() {val interceptorList = mutableListOf<Interceptor>()interceptorList.add(LogInterceptor())interceptorList.add(HeaderInterceptor())val request = Request()val realInterceptorChain = RealInterceptorChain(request, interceptorList, 0)val response = realInterceptorChain.proceed(request)println("main response")
}*/

参考:

https://github.com/leavesCZY/AndroidGuide/blob/master/%E4%B8%BB%E6%B5%81%E5%BC%80%E6%BA%90%E5%BA%93%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%EF%BC%8811%EF%BC%89OkHttp%20%E6%BA%90%E7%A0%81%E8%AF%A6%E8%A7%A3.md

相关文章:

Kotlin 中 OkHttp 使用及解析

build.gradle dependencies {//OkHttpimplementation com.squareup.okhttp3:okhttp:4.9.0 } 简单使用例子 val okHttpClient OkHttpClient.Builder().connectTimeout(Duration.ofSeconds(10)).readTimeout(Duration.ofSeconds(10)).writeTimeout(Duration.ofSeconds(10)).re…...

【C++代码】用栈实现队列,用队列实现栈--代码随想录

队列是先进先出&#xff0c;栈是先进后出。卡哥给了关于C方向关于栈和队列的4个问题&#xff1a; C中stack 是容器么&#xff1f; 使用的stack是属于哪个版本的STL&#xff1f; 使用的STL中stack是如何实现的&#xff1f; stack 提供迭代器来遍历stack空间么&#xff1f; …...

肖sir__linux详解__001

linux详解: 1、ifconfig 查看ip地址 2、6版本&#xff1a;防火墙的命令&#xff1a; service iptables status 查看防火墙状态 service iptables statrt 开启防火墙 service iptables stop 关闭防火墙 service iptables restart 重启防火墙状态 7版本&#xff1a; systemctl s…...

【Android Framework系列】第12章 RecycleView相关原理及四级缓存策略分析

1 RecyclerView简介 RecyclerView是一款非常强大的widget&#xff0c;它可以帮助您灵活地显示列表数据。当我开始学习 RecyclerView的时候&#xff0c;我发现对于复杂的列表界面有很多资源可以参考&#xff0c;但是对于简单的列表展现就鲜有可参考的资源了。虽然RecyclerView的…...

P1886 滑动窗口 /【模板】(双端队列)+双端队列用法

例题 有一个长为 n 的序列 a&#xff0c;以及一个大小为 k 的窗口。现在这个从左边开始向右滑动&#xff0c;每次滑动一个单位&#xff0c;求出每次滑动后窗口中的最大值和最小值。 例如&#xff1a; The array is [1,3,−1,−3,5,3,6,7],and k3。 输入格式 输入一共有两行…...

网络渗透day6-面试01

&#x1f609; 和渗透测试相关的面试问题。 介绍 如果您想自学网络渗透&#xff0c;有许多在线平台和资源可以帮助您获得相关的知识和技能。以下是一些受欢迎的自学网络渗透的平台和资源&#xff1a; Hack The Box: Hack The Box&#xff08;HTB&#xff09;是一个受欢迎的平…...

Docker 及 Docker Compose 安装指南

Docker 是一个开源的容器化平台&#xff0c;可以帮助我们快速构建、打包和运行应用程序。而 Docker Compose 则是用于管理多个容器应用的工具&#xff0c;可以轻松定义和管理多个容器之间的关系。现在&#xff0c;让我们开始安装过程吧&#xff01; docker 安装 apt安装 sudo…...

Gitlab创建一个空项目

1. 创建项目 Project slug是访问地址的后缀&#xff0c;跟前边的ProjectUrl拼在一起&#xff0c;就是此项目的首页地址&#xff1b; Visibility Level选择默认私有即可&#xff0c;选择内部或者公开&#xff0c;就会暴露代码。 勾选Readme选项&#xff0c;这样项目内默认会带…...

C语言-内存分布(STM32内存分析)

C/C内存分布 一、内存组成二、静态区域文本段 &#xff08;Text / 只读区域 RO&#xff09;已初始化读写数据段&#xff08;RW data -- Initialized Data Segment&#xff09;未初始化数据段&#xff08;BSS -- Block Started by Symbol&#xff09; 三、动态区域堆&#xff08…...

Linux上配置NAT

Linux系统上实现NAT上网是一个挑战性的任务&#xff0c;需要对操作系统进行合理的配置。本文将概述在Linux上实现NAT上网&#xff0c;并给出相应的工作步骤。 NAT&#xff0c;即Network Address Translation&#xff0c;是一种网络部署技术&#xff0c;可以在peivate network&…...

springboot实现简单的消息对话

目录 一、前言 二、实战步骤 步骤 1&#xff1a; 步骤 2&#xff1a; 步骤 3&#xff1a; 步骤 4&#xff1a; 一、前言 要在Spring Boot项目中实现消息对话&#xff0c;你可以使用WebSocket技术。WebSocket是一种在客户端和服务器之间提供实时双向通信的协议。 二、实…...

「Tech初见」Linux驱动之blkdev

目录 一、Motivation二、SolutionS1 - 块设备驱动框架&#xff08;1&#xff09;注册块设备&#xff08;2&#xff09;注销块设备&#xff08;3&#xff09;申请 gendisk&#xff08;4&#xff09;删除 gendisk&#xff08;5&#xff09;将 gendisk 加入 kernel&#xff08;6&a…...

ssh配置(二、登录服务器)

一. 登录 linux 服务器的两种方式 使用 ssh用户名密码 的方式登录&#xff0c;但这种方式不安全&#xff0c;密码太简单容易被暴力破解&#xff0c;密码太复杂又不容易记。使用 ssh公私钥 的方式登录。 以上两种方式都可以在图形化软件工具中配置&#xff0c;例如 finalshell…...

pytorch异常——RuntimeError:Given groups=1, weight of size..., expected of...

文章目录 省流异常报错异常截图异常代码原因解释修正代码执行结果 省流 nn.Conv2d 需要的输入张量格式为 (batch_size, channels, height, width)&#xff0c;但您的示例输入张量 x 是 (batch_size, height, width, channels)。因此&#xff0c;需要对输入张量进行转置。 注意…...

【FPGA项目】沙盘演练——基础版报文收发

​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ 第1个虚拟项目 前言 点灯开启了我们的FPGA之路&#xff0c;那么我们来继续沙盘演练。 用一个虚拟项目&#xff0c;来入门练习&#xff0c;以此步入数字逻辑的…...

【C++技能树】继承概念与解析

Halo&#xff0c;这里是Ppeua。平时主要更新C&#xff0c;数据结构算法&#xff0c;Linux与ROS…感兴趣就关注我bua&#xff01; 继承 0. 继承概念0.1 继承访问限定符 1. 基类和派生类对象赋值兼容转换2. 继承中的作用域3. 派生类中的默认成员函数4.友元5.继承中的静态成员6.菱…...

计算机网络 第二节

目录 一&#xff0c;计算机网络的分类 1.按照覆盖范围分 2.按照所属用途分 二&#xff0c;计算机网络逻辑组成部分 1.核心部分 &#xff08;通信子网&#xff09; 1.1电路交换 1.2 分组交换 两种方式的特点 重点 2.边缘部分 &#xff08;资源子网&#xff09; 进程通信的方…...

无涯教程-机器学习 - 矩阵图函数

相关性是有关两个变量之间变化的指示&#xff0c;在前面的章节中&#xff0c;无涯教程讨论了Pearson的相关系数以及相关的重要性&#xff0c;可以绘制相关矩阵以显示哪个变量相对于另一个变量具有较高或较低的相关性。 在以下示例中&#xff0c;Python脚本将为Pima印度糖尿病数…...

Redis 高可用与集群

Redis 高可用与集群 虽然 Redis 可以实现单机的数据持久化&#xff0c;但无论是 RDB 也好或者 AOF 也好&#xff0c;都解决 不了单点宕机问题&#xff0c;即一旦单台 redis 服务器本身出现系统故障、硬件故障等问题后&#xff0c; 就会直接造成数据的丢失&#xff0c;因此需要…...

修改文件名后Git仓上面并没有修改

场景&#xff1a; 我在本地将文件夹名称由Group → group ,执行git push 后&#xff0c;远程分支上的文件名称并没有修改。 原因&#xff1a; 是我绕过了git 直接使用了系统的重命名操作。 在 Git 中&#xff0c;对于已经存在的文件或文件夹进行大小写重命名是一个敏感的操作…...

2025年IDM永久试用完整攻略:无需破解的官方替代方案

2025年IDM永久试用完整攻略&#xff1a;无需破解的官方替代方案 【免费下载链接】IDM-Activation-Script IDM Activation & Trail Reset Script 项目地址: https://gitcode.com/gh_mirrors/id/IDM-Activation-Script 还在为Internet Download Manager的30天试用到期…...

py每日spider案例之网yiyun搜索接口

import requests url=https://api.s0o1.com/API/wyy_music?msg=唯一 response=requests.get(url) for item in response.json().get(data...

第一次降AI率不知道用什么?比话可能是最适合新手的选择

第一次降AI率不知道用什么&#xff1f;比话可能是最适合新手的选择 “学校说要查AI率&#xff0c;我论文肯定过不了&#xff0c;怎么办&#xff1f;” 收到这类消息的频率最近明显增加了。问的人基本都有一个共同特点&#xff1a;之前从来没用过降AI工具&#xff0c;突然被告知…...

GME-Qwen2-VL-2B-Instruct与计算机组成原理教学:可视化理解CPU流水线

GME-Qwen2-VL-2B-Instruct与计算机组成原理教学&#xff1a;可视化理解CPU流水线 你有没有过这样的经历&#xff1f;在学计算机组成原理的时候&#xff0c;面对课本上那些复杂的CPU流水线结构图&#xff0c;感觉就像在看一张密密麻麻的电路板&#xff0c;每个部件都认识&#…...

Next.js Notion Starter Kit代码审查终极指南:确保项目质量的10个关键检查点

Next.js Notion Starter Kit代码审查终极指南&#xff1a;确保项目质量的10个关键检查点 【免费下载链接】nextjs-notion-starter-kit Deploy your own Notion-powered website in minutes with Next.js and Vercel. 项目地址: https://gitcode.com/gh_mirrors/ne/nextjs-not…...

如何快速上手 rx 像素编辑器:新手完全指南

如何快速上手 rx 像素编辑器&#xff1a;新手完全指南 【免费下载链接】rx &#x1f47e; Modern and minimalist pixel editor 项目地址: https://gitcode.com/gh_mirrors/rx/rx rx 是一款现代简约的像素编辑器&#xff0c;专为像素艺术创作设计。本指南将帮助你快速掌…...

从前向渲染到延迟渲染:为什么3A游戏都在用Deferred?

两种算账方式&#xff0c;两种命运从一个餐厅说起 你开了一家餐厅。100桌客人&#xff0c;10个厨师。 方式一&#xff1a;每桌每菜。 服务员端着第一桌的菜单走进厨房。"第一桌要红烧肉。"10个厨师一起做红烧肉。做完了。"第一桌还要糖醋鱼。"10个厨师一起…...

Spring Boot实战:5分钟搞定SSE消息推送(含完整代码示例)

Spring Boot实战&#xff1a;5分钟构建股票行情推送系统&#xff08;SSE全流程指南&#xff09; 1. 为什么选择SSE技术&#xff1f; 在实时数据推送领域&#xff0c;开发者常面临技术选型的困惑。当我们需要实现股票行情更新这类高频单向数据推送场景时&#xff0c;Server-Sent…...

ICLR2022技术解析:AV-HuBERT如何通过多模态掩码预测革新语音视觉表征学习

1. AV-HuBERT&#xff1a;当语音识别遇上"读唇术" 想象一下这样的场景&#xff1a;在嘈杂的餐厅里&#xff0c;你完全听不清对面朋友在说什么&#xff0c;但看着他的嘴唇动作&#xff0c;你却能猜出大概意思。这种人类与生俱来的多模态信息处理能力&#xff0c;正是…...

translategemma-4b-it效果实测:Ollama环境下对模糊/低清/倾斜图片的鲁棒性翻译表现

translategemma-4b-it效果实测&#xff1a;Ollama环境下对模糊/低清/倾斜图片的鲁棒性翻译表现 你有没有遇到过这种情况&#xff1a;在网上找到一张很有用的英文图表&#xff0c;但图片质量很差&#xff0c;要么模糊不清&#xff0c;要么分辨率低得可怜&#xff0c;甚至还有点…...