OkHttp 请求构建和响应处理的完整流程

一、请求构建流程代码示例

1. GET 请求构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 创建OkHttpClient实例
val client = OkHttpClient()

// 构建GET请求
val request = Request.Builder()
.url("https://api.example.com/users")
.header("Authorization", "Bearer token123")
.addHeader("Accept", "application/json")
.get() // GET请求,可省略,因为默认就是GET
.tag(String::class.java, "用户列表请求")
.build()

// 执行请求
val response = client.newCall(request).execute()

2. POST 请求构建 (JSON 数据)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 创建JSON请求体
val json = """
{
"username": "test_user",
"password": "test_password"
}
""".trimIndent()

val mediaType = "application/json; charset=utf-8".toMediaType()
val requestBody = json.toRequestBody(mediaType)

// 构建POST请求
val request = Request.Builder()
.url("https://api.example.com/login")
.header("Content-Type", "application/json")
.post(requestBody) // 设置POST方法和请求体
.build()

// 执行请求
val response = client.newCall(request).execute()

3. POST 表单提交

1
2
3
4
5
6
7
8
9
10
11
// 创建表单请求体
val formBody = FormBody.Builder()
.add("username", "test_user")
.add("password", "test_password")
.build()

// 构建POST请求
val request = Request.Builder()
.url("https://api.example.com/login")
.post(formBody) // 设置POST方法和表单请求体
.build()

4. 文件上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 创建MultipartBody
val file = File("/path/to/file.jpg")
val mediaType = "image/jpeg".toMediaType()
val requestFile = file.asRequestBody(mediaType)

val multipartBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "Profile Picture")
.addFormDataPart("image", "file.jpg", requestFile)
.build()

// 构建POST请求
val request = Request.Builder()
.url("https://api.example.com/upload")
.post(multipartBody)
.build()

二、响应处理流程代码示例

1. 基本响应处理

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
// 执行请求获取响应
val response = client.newCall(request).execute()

try {
// 检查响应是否成功
if (response.isSuccessful) {
// 状态码在200-299之间
val statusCode = response.code
val headers = response.headers

// 获取响应体并转换为字符串
val responseBody = response.body
val responseString = responseBody?.string()

println("响应成功: $statusCode")
println("响应内容: $responseString")
} else {
// 处理错误响应
println("请求失败: ${response.code}")
println("错误信息: ${response.message}")
}
} finally {
// 关闭响应,释放资源
response.close()
}

2. JSON 响应处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 假设使用Gson进行JSON解析
val gson = Gson()

try {
if (response.isSuccessful) {
val responseBody = response.body

// 将响应体转换为字符串
val jsonString = responseBody?.string()

// 解析JSON到数据类
data class User(val id: Int, val name: String, val email: String)
val user = gson.fromJson(jsonString, User::class.java)

println("用户ID: ${user.id}")
println("用户名: ${user.name}")
println("邮箱: ${user.email}")
}
} finally {
response.close()
}

3. 流式处理大文件下载

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
49
50
51
52
53
// 下载文件示例
val request = Request.Builder()
.url("https://example.com/large-file.zip")
.build()

val response = client.newCall(request).execute()

try {
if (!response.isSuccessful) {
throw IOException("下载失败: ${response.code}")
}

// 获取响应体
val responseBody = response.body ?: throw IOException("响应体为空")

// 创建输出文件
val downloadFile = File("/path/to/save/file.zip")
val outputStream = FileOutputStream(downloadFile)

// 使用BufferedSink进行高效写入
val sink = outputStream.sink().buffer()

// 从响应体获取源
val source = responseBody.source()

// 读取数据并写入文件
val bufferSize = 8 * 1024 // 8KB缓冲区
val buffer = Buffer()
var bytesRead: Long

// 显示下载进度
val contentLength = responseBody.contentLength()
var totalBytesRead = 0L

while (source.read(buffer, bufferSize.toLong()).also { bytesRead = it } != -1L) {
sink.write(buffer, bytesRead)
totalBytesRead += bytesRead

// 计算下载进度
if (contentLength > 0) {
val progress = (totalBytesRead * 100 / contentLength).toInt()
println("下载进度: $progress%")
}
}

// 确保所有数据都写入
sink.flush()
sink.close()

println("文件下载完成: ${downloadFile.absolutePath}")
} finally {
response.close()
}

4. 异步请求与响应处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 异步执行请求
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
// 请求失败处理
println("请求失败: ${e.message}")
}

override fun onResponse(call: Call, response: Response) {
// 使用try-finally确保响应关闭
try {
if (response.isSuccessful) {
val responseData = response.body?.string()
println("异步请求成功: $responseData")

// 注意:这里是在OkHttp的工作线程中
// 如果需要更新UI,需要切换到主线程
} else {
println("请求返回错误: ${response.code}")
}
} finally {
response.close()
}
}
})

三、请求和响应的完整生命周期

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
49
50
51
52
53
54
55
56
57
58
// 1. 创建OkHttpClient
val client = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()

// 2. 构建请求
val request = Request.Builder()
.url("https://api.example.com/data")
.header("User-Agent", "OkHttp Example")
.build()

// 3. 创建Call对象
val call = client.newCall(request)

// 4. 执行请求
val response = call.execute()

// 5. 处理响应
try {
// 5.1 检查响应状态
val statusCode = response.code

// 5.2 获取响应头
val contentType = response.header("Content-Type")

// 5.3 处理响应体
if (response.isSuccessful) {
val responseBody = response.body

// 根据Content-Type处理不同类型的响应
when {
contentType?.contains("application/json") == true -> {
// 处理JSON响应
val jsonString = responseBody?.string()
println("JSON响应: $jsonString")
}
contentType?.contains("text/") == true -> {
// 处理文本响应
val textResponse = responseBody?.string()
println("文本响应: $textResponse")
}
else -> {
// 处理二进制响应
val bytes = responseBody?.bytes()
println("二进制响应长度: ${bytes?.size} 字节")
}
}
} else {
// 处理错误响应
println("错误: ${response.code} ${response.message}")
}
} catch (e: Exception) {
println("处理响应时发生异常: ${e.message}")
} finally {
// 6. 关闭响应
response.close()
}

以上代码示例展示了 OkHttp 请求构建和响应处理的完整流程,包括:

  1. 不同类型的请求构建(GET、POST、文件上传等)
  2. 各种响应处理方式(字符串、JSON、文件下载等)
  3. 同步和异步请求的处理差异
  4. 完整的请求-响应生命周期管理

这些示例可以作为实际开发中的参考模板。

作者

Dench

发布于

2025-04-12

更新于

2025-04-12

许可协议

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×