OkHttp的使用

摘要

本文是介绍OKHttp的简单使用。OkHttp目前作为Android网络请求的主力框架,学习和深入OkHttp是非常必要的。目前OkHttp已经更新到4.9.0版本,从4.0版本开始已经采用Kotlin开发,充分利用了Kotlin的特性,如扩展函数,所以与以前版本的使用有一点区别,但框架和思路是没有变化的。本文简单的介绍的GETPOST请求,图片上传还有图文上传的使用,是作为OkHttp系列文章的开篇。

添加依赖

1
2
3
4
# okhttp 4.9版本的依赖
implementation("com.squareup.okhttp3:okhttp:4.9.0")
#网络请求日志拦截器
implementation("com.squareup.okhttp3:logging-interceptor")

入门与使用

1
2
3
val client = OkHttpClient()

val request = Request.Builder().url("http://192.168.1.151:8080/get").get().build()

同步

1
2
3
4
5
thread(start = true) {
client.newCall(request).execute().use {
Log.d(TAG, it.body?.string()?:"null")
}
}

异步

1
2
3
4
5
6
7
8
9
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.d(TAG, e.message!!)
}

override fun onResponse(call: Call, response: Response) {
findViewById<TextView>(R.id.tv).text = response.body.string()
}
})

Request

通过Request.Builder,可以设置网络网络请求的url,method,headers,tag,body,其中tag主要用于跟踪该请求状态,方便debug等。

1
2
3
4
5
6
7
8
val request = Request.Builder()
.tag("test")//添加标签
.addHeader("token","xxm-sz")//添加请求头
//headers会清空之前已设置的header,例如token会被清空
.headers(Headers.Builder().add("accept-encoding","application/json").build())
.url("http://192.168.1.151:8080/get")//请求地址
.get()//请求方法
.build()

如果自定义请求头与默认的相同,则默认的请求头会被修改。下面是Post请求,RequestBody相对于Java语言而言,大多数方法被声明为扩展函数。

1
2
3
4
5
6
val requestBody="data".toRequestBody(null)

val postRequest = Request.Builder()
.url("http://192.168.1.151:8080/post")
.post(requestBody)
.build()

图片上传:

1
2
3
4
5
6
7
8
val file=File("/storage/emulated/0/Download/Screenshot_1614074735.png")
val fileBody=file.asRequestBody()
val filePart=MultipartBody.Builder().addFormDataPart(body = fileBody,name = "image",filename ="test.png").build()

val fileRequest = Request.Builder()
.url("http://192.168.1.151:8080/file")//请求地址
.post(filePart)
.build()

文件与参数上传:

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
fun uploadFileAndParams(url: String,filePath: String,paramsMap:HashMap<String,String>,callback: HttpCallback){
val builder=MultipartBody.Builder().setType(MultipartBody.FORM)
val file = File(filePath)

if (!file.exists() || file.isDirectory) {
throw RuntimeException("the file isn't exit or is directory")
}

val fileBody = file.asRequestBody()
builder.addFormDataPart(body = fileBody, name = "image", filename = "test.png").build()

for (entry in paramsMap){
builder.addFormDataPart(entry.key,entry.value)
}
val fileRequest = Request.Builder()
.url("${baseUrl}${url}")//请求地址
.post(builder.build())
.build()
realRequest(fileRequest,callback)
}

private fun realRequest(request: Request, callback: HttpCallback) {
httpCient.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
callback(false, null, "call:${call.request().url},error:${e.message}")
}

override fun onResponse(call: Call, response: Response) {
if (response.code == 200) {
callback(true, response.body?.string(), response.message)
}else{
callback(false, null, "call:${call.request().url},error:${response.message}")
}
}
})
}