当前位置: 首页 > news >正文

okhttp使用指南

欢迎访问我的主页: https://heeheeaii.github.io/

1. 基础配置

依赖添加

// Gradle (build.gradle.kts)
implementation("com.squareup.okhttp3:okhttp:4.11.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")

单例客户端配置

object HttpClient {val client: OkHttpClient by lazy {OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).addInterceptor(LoggingInterceptor()).addInterceptor(AuthInterceptor()).build()}
}

2. 基本请求方法

GET 请求

// 同步 GET
fun getUser(userId: String): String? {val request = Request.Builder().url("https://api.example.com/users/$userId").build()return try {HttpClient.client.newCall(request).execute().use { response ->if (response.isSuccessful) {response.body?.string()} else {throw Exception("HTTP ${response.code}: ${response.message}")}}} catch (e: Exception) {println("请求失败: ${e.message}")null}
}// 异步 GET
fun getUserAsync(userId: String, callback: (String?) -> Unit) {val request = Request.Builder().url("https://api.example.com/users/$userId").build()HttpClient.client.newCall(request).enqueue(object : Callback {override fun onFailure(call: Call, e: IOException) {callback(null)}override fun onResponse(call: Call, response: Response) {response.use {callback(if (it.isSuccessful) it.body?.string() else null)}}})
}

POST JSON 请求

fun createUser(userData: String): String? {val requestBody = userData.toRequestBody("application/json".toMediaType())val request = Request.Builder().url("https://api.example.com/users").post(requestBody).build()return HttpClient.client.newCall(request).execute().use { response ->if (response.isSuccessful) {response.body?.string()} else {throw Exception("创建失败: ${response.code}")}}
}

POST 表单请求

fun login(username: String, password: String): String? {val formBody = FormBody.Builder().add("username", username).add("password", password).build()val request = Request.Builder().url("https://api.example.com/login").post(formBody).build()return HttpClient.client.newCall(request).execute().use { response ->response.body?.string()}
}

3. 文件操作

文件上传

fun uploadFile(file: File, description: String): String? {val requestBody = MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("description", description).addFormDataPart("file", file.name, file.asRequestBody("application/octet-stream".toMediaType())).build()val request = Request.Builder().url("https://api.example.com/upload").post(requestBody).build()return HttpClient.client.newCall(request).execute().use { response ->response.body?.string()}
}

文件下载

fun downloadFile(url: String, outputFile: File): Boolean {val request = Request.Builder().url(url).build()return try {HttpClient.client.newCall(request).execute().use { response ->if (response.isSuccessful) {response.body?.byteStream()?.use { inputStream ->outputFile.outputStream().use { outputStream ->inputStream.copyTo(outputStream)}}true} else {false}}} catch (e: Exception) {false}
}// 带进度的下载
fun downloadWithProgress(url: String, outputFile: File, onProgress: (progress: Int) -> Unit): Boolean {val request = Request.Builder().url(url).build()return try {HttpClient.client.newCall(request).execute().use { response ->if (response.isSuccessful) {val body = response.body ?: return falseval contentLength = body.contentLength()body.byteStream().use { inputStream ->outputFile.outputStream().use { outputStream ->val buffer = ByteArray(8192)var downloaded = 0Lvar bytesRead: Intwhile (inputStream.read(buffer).also { bytesRead = it } != -1) {outputStream.write(buffer, 0, bytesRead)downloaded += bytesReadif (contentLength > 0) {val progress = (downloaded * 100 / contentLength).toInt()onProgress(progress)}}}}true} else {false}}} catch (e: Exception) {false}
}

4. 实用拦截器

日志拦截器

class LoggingInterceptor : Interceptor {override fun intercept(chain: Interceptor.Chain): Response {val request = chain.request()val startTime = System.nanoTime()println("发送请求: ${request.method} ${request.url}")val response = chain.proceed(request)val endTime = System.nanoTime()println("收到响应: ${response.code} in ${(endTime - startTime) / 1e6}ms")return response}
}

认证拦截器

class AuthInterceptor(private val token: String) : Interceptor {override fun intercept(chain: Interceptor.Chain): Response {val originalRequest = chain.request()val authenticatedRequest = originalRequest.newBuilder().header("Authorization", "Bearer $token").build()return chain.proceed(authenticatedRequest)}
}

重试拦截器

class RetryInterceptor(private val maxRetries: Int = 3) : Interceptor {override fun intercept(chain: Interceptor.Chain): Response {var request = chain.request()var response = chain.proceed(request)var retryCount = 0while (!response.isSuccessful && retryCount < maxRetries) {retryCount++println("重试第 $retryCount 次: ${request.url}")response.close()response = chain.proceed(request)}return response}
}

缓存拦截器

class CacheInterceptor(private val maxAge: Int = 60) : Interceptor {override fun intercept(chain: Interceptor.Chain): Response {val request = chain.request()val response = chain.proceed(request)return response.newBuilder().header("Cache-Control", "public, max-age=$maxAge").build()}
}

5. 高级配置

缓存设置

val cacheSize = 10 * 1024 * 1024L // 10MB
val cache = Cache(File(context.cacheDir, "http-cache"), cacheSize)val clientWithCache = OkHttpClient.Builder().cache(cache).addNetworkInterceptor(CacheInterceptor()).build()

HTTPS 配置

// 信任所有证书(仅用于开发环境)
fun createUnsafeClient(): OkHttpClient {val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()})val sslContext = SSLContext.getInstance("SSL")sslContext.init(null, trustAllCerts, SecureRandom())return OkHttpClient.Builder().sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager).hostnameVerifier { _, _ -> true }.build()
}// 证书锁定(生产环境推荐)
val clientWithPinning = OkHttpClient.Builder().certificatePinner(CertificatePinner.Builder().add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=").build()).build()

6. 工具类封装

HTTP 工具类

class HttpUtil private constructor() {companion object {private val client = OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }).build()// GET 请求fun get(url: String, headers: Map<String, String> = emptyMap()): String? {val requestBuilder = Request.Builder().url(url)headers.forEach { (key, value) -> requestBuilder.addHeader(key, value) }return try {client.newCall(requestBuilder.build()).execute().use { response ->if (response.isSuccessful) response.body?.string() else null}} catch (e: Exception) {null}}// POST JSONfun postJson(url: String, json: String, headers: Map<String, String> = emptyMap()): String? {val requestBody = json.toRequestBody("application/json".toMediaType())val requestBuilder = Request.Builder().url(url).post(requestBody)headers.forEach { (key, value) -> requestBuilder.addHeader(key, value) }return try {client.newCall(requestBuilder.build()).execute().use { response ->if (response.isSuccessful) response.body?.string() else null}} catch (e: Exception) {null}}// 异步请求fun getAsync(url: String, callback: (String?) -> Unit) {val request = Request.Builder().url(url).build()client.newCall(request).enqueue(object : Callback {override fun onFailure(call: Call, e: IOException) {callback(null)}override fun onResponse(call: Call, response: Response) {response.use { callback(if (it.isSuccessful) it.body?.string() else null) }}})}}
}

API 响应包装类

data class ApiResponse<T>(val code: Int,val message: String,val data: T?
) {val isSuccess: Boolean get() = code == 200
}// 使用示例
inline fun <reified T> parseResponse(json: String): ApiResponse<T>? {return try {Gson().fromJson(json, object : TypeToken<ApiResponse<T>>() {}.type)} catch (e: Exception) {null}
}

7. 实际使用示例

用户服务示例

class UserService {private val baseUrl = "https://api.example.com"fun login(email: String, password: String): ApiResponse<String>? {val loginData = mapOf("email" to email, "password" to password)val json = Gson().toJson(loginData)val response = HttpUtil.postJson("$baseUrl/login", json)return response?.let { parseResponse<String>(it) }}fun getUserProfile(token: String): ApiResponse<User>? {val headers = mapOf("Authorization" to "Bearer $token")val response = HttpUtil.get("$baseUrl/profile", headers)return response?.let { parseResponse<User>(it) }}fun uploadAvatar(token: String, avatarFile: File, callback: (Boolean) -> Unit) {val requestBody = MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("avatar", avatarFile.name,avatarFile.asRequestBody("image/*".toMediaType())).build()val request = Request.Builder().url("$baseUrl/upload-avatar").addHeader("Authorization", "Bearer $token").post(requestBody).build()HttpClient.client.newCall(request).enqueue(object : Callback {override fun onFailure(call: Call, e: IOException) {callback(false)}override fun onResponse(call: Call, response: Response) {callback(response.isSuccessful)}})}
}

8. 调试和测试

调试技巧

// 详细日志记录
val loggingInterceptor = HttpLoggingInterceptor().apply {level = HttpLoggingInterceptor.Level.BODY
}// 网络状态监控
class NetworkStatusInterceptor : Interceptor {override fun intercept(chain: Interceptor.Chain): Response {val request = chain.request()println("请求: ${request.method} ${request.url}")println("请求头: ${request.headers}")val startTime = System.currentTimeMillis()val response = chain.proceed(request)val endTime = System.currentTimeMillis()println("响应: ${response.code} (${endTime - startTime}ms)")println("响应头: ${response.headers}")return response}
}

Mock 数据

class MockInterceptor : Interceptor {override fun intercept(chain: Interceptor.Chain): Response {val request = chain.request()// 根据 URL 返回模拟数据return when {request.url.toString().contains("/users/123") -> {val mockResponse = """{"id":123,"name":"测试用户"}"""Response.Builder().request(request).protocol(Protocol.HTTP_1_1).code(200).message("OK").body(mockResponse.toResponseBody("application/json".toMediaType())).build()}else -> chain.proceed(request)}}
}
http://www.dtcms.com/a/403410.html

相关文章:

  • 新余专业做淘宝网站2022年最新热点素材
  • 马鞍山网站建设制作中文网站怎么做英文版
  • GeoServer安装,并发布MapBox使用的矢量切片服务(pbf格式)(基于windows操作系统,使用shape文件发布)
  • 以AI科技重塑乳业生态,以京北品质服务健康中国 链农科技总经理马旭海专访
  • VMware安装 Rocky Linux 为后续docker k8s 实验做准备 自用 实践笔记(一)
  • Pyqt6开发的可以hexo博客一键创文章,发文章,统计文章。命令包装工具。
  • 链农科技亮相龙岗万达广场:“京北助力·舞动岭南”文艺展演
  • C语言(长期更新)第23讲:编译和链接
  • 怎么做网站后端手机登录凡科网
  • 如何自查家里宽带是否有公网IPv4?就几步。
  • Android studio导入OpenCV报“Unresolved reference: android“
  • 如何管理网站域名服务器做php网站
  • (Arxiv-2025)OmniInsert:无遮罩视频插入任意参考通过扩散 Transformer 模型
  • 大模型实战:通义万相2.1-文生视频-1.3B
  • 【C语言】统计二进制中1的个数:三种方法的比较与分析
  • C语言:数组元素逆序存放
  • C++(day1)
  • 如何让百度抓取网站wordpress 免费插件
  • 无人机无线电测距模块技术要点与难点
  • 逻辑回归中的成本损失函数全解析:从数学推导到实际应用
  • 组件化思维(下):表单与交互组件,倾听用户的心声
  • 机器学习——逻辑回归详解
  • wordpress做英文站最打动人心的广告语
  • 支持向量机深度解析:从数学原理到工程实践的完整指南——流式在线学习、增量 SVM 与万亿参数时代的挑战
  • 时间复杂度与空间复杂度系统梳理与实战
  • 三轴正交磁力矩器输出力矩计算原理及实现
  • 小组网站建设方案书网站seo优化关键词快速排名上首页
  • 淘宝cms建站wordpress调取某页面
  • STM32的HAL库驱动ADS124S08进行PT100温度采集
  • 软件报错处理合集,大部分情况需要下载Webview2、.NET4.8、获取C盘管理员权限等