OkHTTP的一些配置
请求头(Header)信息编辑
val request = Request.Builder() //创建Request实例
.url("https://api.github.com/repos/square/okhttp/issues") //配置请求URL
.header("User-Agent", "OkHttp Headers.java") //设置请求头,如果还配置了其他请求头信息,之前配置的会被清空
.addHeader("Accept", "application/json; q=0.5") //添加请求头信息,不会清空之前的
.addHeader("Accept", "application/vnd.github.v3+json") //同上
.build() //构建包含以上信息的Request
Response内容Json信息解析
@JsonClass(generateAdapter = true)
data class Gist(var files: Map?)
@JsonClass(generateAdapter = true)
data class GistFile(var content: String?)
......
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
//过去json信息,并且遍历
val gist = gistJsonAdapter.fromJson(response.body!!.source())
for ((key, value) in gist!!.files!!) {
println(key)
println(value.content)
}
......
缓存配置
val client: OkHttpClient = OkHttpClient.Builder()
.cache(Cache(
directory = cacheDirectory,
maxSize = 10L * 1024L * 1024L // 10 MiB
))
.build()
请求超时配置Timeout
val client: OkHttpClient = OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.writeTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.callTimeout(10, TimeUnit.SECONDS)
.build()
关闭请求
......
val call = client.newCall(request)
......
call.cancel()
在现有Client的基础上克隆一个新的配置
val client1 = client.newBuilder()
.readTimeout(500, TimeUnit.MILLISECONDS)
.build()
携带认证信息的请求
fun whitAuthenticator() {
val client = OkHttpClient.Builder()
.authenticator(object : Authenticator { //构建认证信息实例,实现抽象方法
@Throws(IOException::class)
override fun authenticate(route: Route?, response: Response): Request? {
if (response.request.header("Authorization") != null) {
return null // Give up, we've already attempted to authenticate.
}
println("Authenticating for response: $response")
println("Challenges: ${response.challenges()}")
val credential = Credentials.basic("jesse", "password1")
return response.request.newBuilder()
.header("Authorization", credential)
.build()
}
})
.build()
val request = Request.Builder()
.url("http://publicobject.com/secrets/hellosecret.txt")
.build()
//......
}
Get请求
同步Get
fun syncGet() {
val client = OkHttpClient()
//构建请求信息
val request = Request.Builder()
.url("https://publicobject.com/helloworld.txt")
.build()
//创建同步连接
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
for ((name, value) in response.headers) {
println("$name: $value")
}
println(response.body!!.string())
}
}
异步Get
fun syncGet() {
val client = OkHttpClient()
//构建Request请求信息
val request = Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build()
//创建异步连接并且添加Callback处理
client.newCall(request).enqueue(object : Callback {
//失败处理方案
override fun onFailure(call: Call, e: java.io.IOException) {
e.printStackTrace()
}
//拿到返回结果处理方案
override fun onResponse(call: Call, response: Response) {
response.use {
//如果返回的状态码不是200~300,抛出异常
if (!response.isSuccessful) throw IOException("Unexpected code $response")
//取出Headers信息
for ((name, value) in response.headers) {
println("$name: $value")
}
//输出body的字符信息
println(response.body!!.string())
}
}
})
}
同步异步的区别
同步用client.newCall(request).use{......}异步采用 client.newCall(request).enqueue(object:Callback{......})
Post请求
字符串Post请求
fun postString() {
val client = OkHttpClient()
//请求字符串信息
val postBody = """
|Releases
|--------
|
| * _1.0_ May 6, 2013
| * _1.1_ June 15, 2013
| * _1.2_ August 11, 2013
|""".trimMargin()
//构建请求信息
val request = Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(postBody.toRequestBody("text/x-markdown; charset=utf-8".toMediaType())) // 设置为Post请求,添加请求信息,且设置请求信息类型
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
println(response.body!!.string())
}
}
流信息Post请求
fun postStream() {
val client = OkHttpClient()
//请求消息体的类型配置参数
val MEDIA_TYPE_MARKDOWN = "text/x-markdown; charset=utf-8".toMediaType()
//创建请求的消息体
val requestBody = object : RequestBody() {
override fun contentType() = MEDIA_TYPE_MARKDOWN
//构建输出流信息
override fun writeTo(sink: BufferedSink) {
sink.writeUtf8("Numbers\n")
sink.writeUtf8("-------\n")
for (i in 2..997) {
sink.writeUtf8(String.format(" * $i = ${factor(i)}\n"))
}
}
private fun factor(n: Int): String {
for (i in 2 until n) {
val x = n / i
if (x * i == n) return "${factor(x)} × $i"
}
return n.toString()
}
}
val request = Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(requestBody) //设置Post模式,且传入Post的消息体
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
println(response.body!!.string())
}
}
File信息Post请求(上传)
//请求信息类型配置
val MEDIA_TYPE_MARKDOWN = "text/x-markdown; charset=utf-8".toMediaType()
//构建文件实例
val file = File("README.md")
val request = Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(file.asRequestBody(MEDIA_TYPE_MARKDOWN)) //Post请求
.build()
Form信息Post请求
//构建from信息
val formBody = FormBody.Builder()
.add("search", "Jurassic Park")
.build()
val request = Request.Builder()
.url("https://en.wikipedia.org/w/index.php")
.post(formBody) //设置Post请求
.build()
多种类型Post请求
val IMGUR_CLIENT_ID = "9199fdef135c122"
val MEDIA_TYPE_PNG = "image/png".toMediaType()
//构建请求信息
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM) //Form类型的多类型请求
.addFormDataPart("title", "Square Logo") //Key value类型的请求信息
.addFormDataPart("image", "logo-square.png",
File("docs/images/logo-square.png").asRequestBody(MEDIA_TYPE_PNG)) //图片类型的请求信息
.build()
val request = Request.Builder()
.header("Authorization", "Client-ID $IMGUR_CLIENT_ID")
.url("https://api.imgur.com/3/image")
.post(requestBody) //Post请求
.build()
评论区