OkHttp3 (一)——客户端对象
标签(空格分隔): OkHttp3
版本:4
作者:陈小默
声明:禁止商业,禁止转载
[toc]
开始前的示例
我们需要一个实际的例子来演示OkHttp的简单用法
val NARUTO = "http://tupian.enterdesk.com/2013/xll/007/27/10/8.jpg"
fun main(args: Array<String>) {
//1,创建请求客户端
val client: OkHttpClient = OkHttpClient()
//2,创建请求对象
val request: Request = Request.Builder().url(NARUTO).build()
//3,通过客户端和请求生成一个调用对象
val call: Call = client.newCall(request)
//4,执行调用对象并获得响应对象
val response: Response = call.execute()
//5,判断响应状态
if (response.isSuccessful) {
val output = FileOutputStream(File(LOCAL_PATH, "Naruto.jpg"))
//6,从响应对象中获取响应体对象
val body: ResponseBody = response.body()
//7,从响应体对象中获取数据
val bytes = body.bytes()
output.write(bytes)
output.close()
}
//8,关闭响应对象
response.close()
}
上面这个例子通过OkHttp3下载了一张鸣人的海报。从例子中可以看出使用OkHttp3进行简单请求的基本步骤:
- 创建请求客户端
- 创建请求对象
- 通过客户端和请求生成一个调用对象
- 执行调用对象并获得响应对象
- 判断响应状态
- 从响应对象中获取响应体对象
- 从响应体对象中获取数据
- 关闭响应对象
客户端对象
OkHttpClient
是一个客户端对象,其作用相当于一个浏览器,用来发送HTTP请求和处理请求。通常情况下,建议在一系列请求中使用同一个客户端对象,也就是说,在程序中使用单例模式创建客户端对象。这是因为,每一个客户端对象都会创建它自己的连接池与线程池,如果在每次访问网络都创建一个客户端对象的话,很可能会造成内存溢出。
创建客户端的方式
1,创建带有默认设置的客户端对象
如果我们对于访问设置没有什么特殊要求的话,可以采用如下方式创建一个默认设置的客户端对象:
//单例模式创建一个默认设置的客户端对象
object OkHttpUtil {
val client = OkHttpClient()
}
fun main(args: Array<String>) {
val client = OkHttpUtil.client
}
2,创建自定义配置的客户端对象
当我们需要对客户端做一些配置的时候,比如设置Cookie管理器、更改缓存位置和大小。这时候默认的设置的客户端就已经满足不了需求了,于是我们可以通过下列方法去实现自定义配置的客户端。
object OkHttpUtil {
val client = OkHttpClient.Builder()
.cookieJar(cookie)
.cache(Cache(File(LOCAL_PATH), 1024L))
.build()
}
fun main(args: Array<String>) {
val client = OkHttpUtil.client
}
3,继承已有客户端配置
在实际工作过程当中,我们可能会遇见这样的场景,比如:某些请求需要使用另一种Cookie管理器,但是其他配置信息与原有的一致。这种情况下,我们再完全重新开始创建一个对象肯定是不友好的。于是我们可以通过以下方式继承一个原有客户端的配置,并对其进行修改。
注:修改配置并不会影响原有的客户端对象,而是会生成一个新的客户端对象。
fun main(args: Array<String>) {
val client = OkHttpUtil.client
val newClient = client.newBuilder()
.cookieJar(cookie)
.build()
}
在不需要时关闭客户端
在一般的应用场景我们可能不需要关闭客户端,比如Android应用需要始终保持网络通畅。但是也有一些场景可能只是暂时连接网络或者用户主动关闭网络连接。那么我们就需要关闭OkHttp客户端以释放资源。
首先,我们需要关闭调度器服务。这一步会导致以后所有使用此客户端的请求都会被残忍拒接。
client.dispatcher().executorService().shutdown()
接下来,我们需要关闭网络连接池。此时连接池的守护线程会立即退出。
Clear the connection pool with evictAll(). Note that the connection pool's daemon thread may not exit immediately.
client.connectionPool().evictAll()
如果客户端使用了缓存机制,那么最后一步我们需要关闭缓存。如果在关闭之后访问了缓存的话会导致异常。
client.cache().close()
OkHttp为HTTP/2连接使用了一个守护线程,它会在闲置时自动退出。