OkHttp中interceptors拦截器

OkHttp拦截器是一种强大的机制,可以监视、重写和重试调用

1、LogInterceptor 示例代码
class LogInterceptor:Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val mRequest=chain.request()

        // startTime
        val 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 查看应用拦截器日志
// request
 D/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-transform
    Connection: keep-alive
    Content-Type: text/html
    Date: Thu, 08 Jul 2021 07:38:20 GMT
    Last-Modified: Mon, 23 Jan 2017 13:23:46 GMT
    Pragma: no-cache
    Server: bfe/1.0.8.18
    Set-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 Example
    Host: www.publicobject.com
    Connection: Keep-Alive
    Accept-Encoding: gzip

D/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 GMT
    Content-Type: text/html
    Content-Length: 194
    Connection: keep-alive
    Location: https://publicobject.com/helloworld.txt
    
D/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 Example
    Host: publicobject.com
    Connection: Keep-Alive
    Accept-Encoding: gzip

D/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 GMT
    Content-Type: text/plain
    Content-Length: 1759
    Last-Modified: Tue, 27 May 2014 02:35:47 GMT
    Connection: keep-alive
    ETag: "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)
        }

        // compressedRequest
        val 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 = body
    override 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)
        // setMaxCacheAge
        return mOriginResponse.newBuilder().header("Cache-Control", "max-age=60").build()
    }
}
  • 参考:https://square.github.io/okhttp/interceptors/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值