[TOC]

文章参考:https://www.jianshu.com/p/abcc381a3a27

概述

OkHttp3的使用

添加依赖库

具体请求

Http 请求有多种类型,常用的分为 Get 和 Post,而 POST 又分为 Form 和 Multiple 等,下面我们以Get请求为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 1.创建OkHttpClient 对象,
// var client = OkHttpClient();//方式一
//方式二:
val client = OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build()
//2.创建请求对象并添加请求参数信息
val request = Request.Builder().url("").build()
//3.构建进行请求操作的call对象
val call = client.newCall(request)

//同步请求 Call (RealCall)—>execute() 返回response
// val response = client.newCall(request).execute()
//异步请求 Call (RealCall)—>enqueue()
call.enqueue(
object : Callback {
override fun onFailure(call: Call, e: IOException) {
println(e.stackTrace.toString())
}

@Throws(IOException::class)
override fun onResponse(call: Call, response: Response) {
println(response.body.toString())
}
})

  • 首先使用OkHttpClint的构造OkHttpClient()或者Build模式构建一个OkHttpClint的对象实例;
  • 使用构建者模式构建一个Request对象,通过OkHttpClient和Request对象,构建出Call对象;
  • 执行call的enqueue()(异步请求)或者execute()(同步请求)。

注意:在实际开发中建议将OkHttpClient对象的创建封装成单例对象, 因为每个 OkHttpClient 对象都管理自己独有的线程池和连接池,复用连接池和线程池能够减少延迟、节省内存。

源码分析

OkHttpClient

Builder的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

// 对于类内部声明的成员:
// private 意味着只在这个类内部(包含其所有成员)可见;
// protected—— 和 private一样 + 在子类中可见。
// internal —— 能见到类声明的 本模块内 的任何客户端都可见其 internal 成员;
// public —— 能见到类声明的任何客户端都可见其 public 成员。
internal constructor(okHttpClient: OkHttpClient) : this() {
// 调度器,通过双端队列保存Calls(同步&异步Call) 非常重要!!!!!!
this.dispatcher = okHttpClient.dispatcher
// 连接池 TODO
this.connectionPool = okHttpClient.connectionPool
// OKHttp的连接器
this.interceptors += okHttpClient.interceptors
// 网络连接器
this.networkInterceptors += okHttpClient.networkInterceptors
this.eventListenerFactory = okHttpClient.eventListenerFactory
this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure
this.authenticator = okHttpClient.authenticator
// 本地重定向
this.followRedirects = okHttpClient.followRedirects
// 安全套结重定向
this.followSslRedirects = okHttpClient.followSslRedirects
//
this.cookieJar = okHttpClient.cookieJar
this.cache = okHttpClient.cache
// 域名解析器
this.dns = okHttpClient.dns
// 代理对象
this.proxy = okHttpClient.proxy
this.proxySelector = okHttpClient.proxySelector
this.proxyAuthenticator = okHttpClient.proxyAuthenticator
this.socketFactory = okHttpClient.socketFactory
this.sslSocketFactoryOrNull = okHttpClient.sslSocketFactoryOrNull
this.x509TrustManagerOrNull = okHttpClient.x509TrustManager
this.connectionSpecs = okHttpClient.connectionSpecs
this.protocols = okHttpClient.protocols
this.hostnameVerifier = okHttpClient.hostnameVerifier
this.certificatePinner = okHttpClient.certificatePinner
this.certificateChainCleaner = okHttpClient.certificateChainCleaner
this.callTimeout = okHttpClient.callTimeoutMillis
// 连接超时、读取超时、写入超时
this.connectTimeout = okHttpClient.connectTimeoutMillis
this.readTimeout = okHttpClient.readTimeoutMillis
this.writeTimeout = okHttpClient.writeTimeoutMillis
this.pingInterval = okHttpClient.pingIntervalMillis
this.minWebSocketMessageToCompress = okHttpClient.minWebSocketMessageToCompress
this.routeDatabase = okHttpClient.routeDatabase
}

实例化RealCall对象,传入request,准备进行请求

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

所以我们来看RealCall的enqueue异步调用的方法