本文主要是介绍OkHttp中interceptors拦截器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
OkHttp拦截器是一种强大的机制,可以监视、重写和重试调用
1、LogInterceptor 示例代码
class LogInterceptor:Interceptor {override fun intercept(chain: Interceptor.Chain): Response {val mRequest=chain.request()// startTimeval startTime=System.currentTimeMillis()LogUtil.D(log = "Sending request url== ${mRequest.url} " +" connection== ${chain.connection()} " +" headers==${mRequest.headers}")val mResponse=chain.proceed(mRequest)val endTime=System.currentTimeMillis()LogUtil.D(log="Received response url== ${mResponse.request.url} " +" costTime== ${endTime-startTime}ms"+" header== ${mResponse.headers}")return mResponse}
}
2、拦截器使用注意事项
调用chain.process(request)是每个拦截器实现的关键部分,该方法是所有HTTP请求产生响应的地方。如果chain.proceed(request)被多次调用,则必须关闭先前的响应体,否则会发生崩溃。
多个拦截器可以连接起来使用,假设有一个压缩拦截器和一个校验拦截器:你需要决定是先压缩数据然后校验,还是校验和然后压缩。OkHttp 使用列表来跟踪拦截器,拦截器按顺序调用。
3、OkHttp拦截器交互图
4、应用拦截器
- 1、 添加应用拦截器
OkHttpClient.Builder().addInterceptor(LogInterceptor()).build()
- 2 、请求www.baidu.com 查看应用拦截器日志
// requestD/tag: Sending request url== https://www.baidu.com/ connection== null headers==// response
D/tag: Received response url== https://www.baidu.com/ costTime== 145ms header== Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transformConnection: keep-aliveContent-Type: text/htmlDate: Thu, 08 Jul 2021 07:38:20 GMTLast-Modified: Mon, 23 Jan 2017 13:23:46 GMTPragma: no-cacheServer: bfe/1.0.8.18Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/Transfer-Encoding: chunked
- 3、应用拦截器只打印了一遍日志
6、使用网络拦截器 NetworkInterceptor
注册网络拦截器非常相似。调用addNetworkInterceptor()而不是addInterceptor()
- 1、添加网络拦截器
OkHttpClient.Builder().addNetworkInterceptor(LogInterceptor()).build()
- 2、请求https://www.publicobject.com/helloworld.txt,网络拦截器日志
D/tag: Sending request url== https://www.publicobject.com/helloworld.txt connection== Connection{www.publicobject.com:443, proxy=DIRECT hostAddress=www.publicobject.com/54.187.32.157:443 cipherSuite=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 protocol=http/1.1} headers==User-Agent: OkHttp ExampleHost: www.publicobject.comConnection: Keep-AliveAccept-Encoding: gzipD/tag: Received response url== https://www.publicobject.com/helloworld.txt costTime== 214ms header== Server: nginx/1.10.3 (Ubuntu)Date: Thu, 08 Jul 2021 09:30:19 GMTContent-Type: text/htmlContent-Length: 194Connection: keep-aliveLocation: https://publicobject.com/helloworld.txtD/tag: Sending request url== https://publicobject.com/helloworld.txt connection== Connection{publicobject.com:443, proxy=DIRECT hostAddress=publicobject.com/54.187.32.157:443 cipherSuite=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 protocol=http/1.1} headers==User-Agent: OkHttp ExampleHost: publicobject.comConnection: Keep-AliveAccept-Encoding: gzipD/tag: Received response url== https://publicobject.com/helloworld.txt costTime== 493ms header== Server: nginx/1.10.3 (Ubuntu)Date: Thu, 08 Jul 2021 09:30:20 GMTContent-Type: text/plainContent-Length: 1759Last-Modified: Tue, 27 May 2014 02:35:47 GMTConnection: keep-aliveETag: "5383fa03-6df"Accept-Ranges: bytes
2021-07-08 17:30:23.855 19772-19847/com.example.myapplication D/tag: get success response=== okhttp3.internal.http.RealResponseBody@93be2de
- 3、网络拦截器打印了两次日志,一次用于初始化请求,一次用于进行重定向请求。相较于普通拦截器网络拦截器包含更多的信息,包括Hosts、 Accept-Encoding等
7、应用拦截器与网络拦截器特点
1) 应用拦截器
- 无需担心重定向和重试等中间响应。
- 始终调用一次,即使 HTTP 响应是从缓存中提供的。
- 遵循应用程序的原始意图。不关心 OkHttp 注入的标头,如If-None-Match.
- 缓存命中时将拦截器短路,不调用Chain.proceed()。
- 允许重试并多次调用Chain.proceed()。
- 可以使用 withConnectTimeout、withReadTimeout、withWriteTimeout控制请求超时时长
2) 网络拦截器
- 能够对重定向和重试等中间响应进行操作。
- 不会因为使用缓存响应而不发生调用。
- 可以像通过网络传输一样观察数据。
- 以携带请求的方式访问Connection
8、重写请求
- 应用拦截器可以用来添加、移除、替换请求头headers,能够用来转换requests中的请求体,下面为使用应用拦截器进行gzip压缩例子:
- GzipRequestInterceptor
class GzipRequestInterceptor : Interceptor {override fun intercept(chain: Interceptor.Chain): Response {val originRequest = chain.request()if (originRequest == null || originRequest.header("Content-Encoding") != null) {return chain.proceed(originRequest)}// compressedRequestval compressedRequest = originRequest.newBuilder().header("Content-Encoding", "gzip").method(originRequest.method, originRequest.body?.let { CustomRequestBody(it) }).build()return chain.proceed(compressedRequest)}
}class CustomRequestBody(body: RequestBody) : RequestBody() {private val mBody = bodyoverride fun contentType(): MediaType? {return mBody.contentType()}override fun writeTo(sink: BufferedSink) {val gzipSink = GzipSink(sink).buffer()mBody.writeTo(gzipSink)gzipSink.close()}override fun contentLength(): Long {return -1}}
9、重写响应
- 通常情况下,OkHttp会帮我们处理响应头并返回响应体,但是一些业务中可能不满足需求,可以对响应头进行重写,满足需求。
- 代码示例
class CacheAgeInterceptor : Interceptor {override fun intercept(chain: Interceptor.Chain): Response {val mOriginRequest = chain.request()val mOriginResponse = chain.proceed(mOriginRequest)// setMaxCacheAgereturn mOriginResponse.newBuilder().header("Cache-Control", "max-age=60").build()}
}
- 参考:https://square.github.io/okhttp/interceptors/
这篇关于OkHttp中interceptors拦截器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!