📖 目录
-
[为什么要封装 Retrofit + OkHttp](#为什么要封装 Retrofit + OkHttp)
-
[支持多 BaseUrl 的设计](#支持多 BaseUrl 的设计)
-
[Token 自动刷新机制](#Token 自动刷新机制)
💬 前言
在 Android 项目开发中,网络请求几乎是所有业务模块的基础。而在众多方案中,Retrofit + OkHttp 无疑是最稳定、最高效的组合。
它不仅支持注解式接口定义、自动序列化,还能与协程完美结合,轻松实现异步网络通信。
本文将从基础到进阶,带你实现一套「企业级」网络层封装,让你的代码更优雅、更安全、更可维护。
⚙️ 为什么要封装 Retrofit + OkHttp
在小型项目中,直接使用 Retrofit 足够简单;
但随着业务扩展,你可能会遇到以下痛点:
-
不同模块需要使用 不同的 BaseUrl;
-
接口响应结构不一致,需要统一解析;
-
Token 失效需要自动刷新;
-
需要统一的异常处理机制;
-
想让 ViewModel 调用更简洁。
这些问题如果不统一封装,会导致项目结构混乱、维护困难。
因此,我们需要构建一个「高内聚、低耦合」的网络请求框架。
🧱 基础封装思路
Retrofit 是一个「上层封装」,核心依赖 OkHttp:
层级 | 功能 | 说明 |
---|---|---|
OkHttp | 网络层 | 负责请求发送、拦截、缓存、超时 |
Retrofit | 封装层 | 负责接口注解解析、数据转换 |
协程 + Result | 安全层 | 负责异常捕获与结果返回 |
我们将从 OkHttp 开始封装,逐步构建整个网络体系。
🌐 支持多 BaseUrl 的设计
1. 使用场景
在多模块项目中,不同业务接口往往属于不同域名:
模块 | BaseUrl |
---|---|
用户中心 | https://user.api.example.com/ |
支付模块 | https://pay.api.example.com/ |
上传模块 | https://upload.api.example.com/ |
Retrofit 默认只能设置一个 baseUrl
,
因此我们需要通过 拦截器 + Header 标识 来动态替换。
2. BaseUrlInterceptor.kt
Kotlin
class BaseUrlInterceptor : Interceptor {
companion object {
const val HEADER_BASE_URL = "Base-Url" // 自定义 Header 名
}
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val baseUrlHeader = request.header(HEADER_BASE_URL)
// 如果请求头中包含自定义 BaseUrl
if (!baseUrlHeader.isNullOrEmpty()) {
val newUrl = request.url.newBuilder()
.scheme("https")
.host(baseUrlHeader)
.build()
val newRequest = request.newBuilder()
.url(newUrl)
.removeHeader(HEADER_BASE_URL) // 使用完后移除
.build()
return chain.proceed(newRequest)
}
// 默认请求
return chain.proceed(request)
}
}
3. RetrofitManager.kt
Kotlin
object RetrofitManager {
private const val DEFAULT_BASE_URL = "https://user.api.example.com/"
private val okHttpClient by lazy {
OkHttpClient.Builder()
.addInterceptor(BaseUrlInterceptor())
.addInterceptor(TokenInterceptor())
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.build()
}
fun getService(baseUrl: String = DEFAULT_BASE_URL): Retrofit {
return Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
}
使用示例:
Kotlin
val userApi = RetrofitManager.getService().create(UserApi::class.java)
val payApi = RetrofitManager.getService("https://pay.api.example.com/").create(PayApi::class.java)
🧩 统一响应模型与错误处理
1. 定义统一返回结构
Kotlin
data class BaseResponse<T>(
val code: Int,
val msg: String?,
val data: T?
) {
fun isSuccess() = code == 200
}
2. 安全请求封装(协程版)
Kotlin
suspend fun <T> safeApiCall(apiCall: suspend () -> BaseResponse<T>): Result<T> {
return try {
val response = apiCall()
if (response.isSuccess()) {
Result.success(response.data!!)
} else {
Result.failure(Exception(response.msg ?: "未知错误"))
}
} catch (e: IOException) {
Result.failure(Exception("网络连接失败"))
} catch (e: HttpException) {
Result.failure(Exception("网络错误: ${e.code()}"))
} catch (e: Exception) {
Result.failure(e)
}
}
3. ViewModel 调用示例
Kotlin
class LoginViewModel : ViewModel() {
private val _loginState = MutableLiveData<Result<LoginResponse>>()
val loginState: LiveData<Result<LoginResponse>> = _loginState
fun login(username: String, password: String) {
viewModelScope.launch {
val result = safeApiCall {
RetrofitManager.getService().create(UserApi::class.java)
.login(username, password)
}
_loginState.value = result
}
}
}
🔑 Token 自动刷新机制
Kotlin
class TokenInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer ${TokenManager.token}")
.build()
val response = chain.proceed(request)
// Token 过期处理
if (response.code == 401) {
synchronized(this) {
val newToken = TokenManager.refreshToken()
if (newToken != null) {
val newRequest = request.newBuilder()
.removeHeader("Authorization")
.addHeader("Authorization", "Bearer $newToken")
.build()
return chain.proceed(newRequest)
}
}
}
return response
}
}
📦 网络层完整结构
network/ ├── ApiService.kt # 接口定义 ├── RetrofitManager.kt # Retrofit 实例 ├── BaseUrlInterceptor.kt # 多域名支持 ├── TokenInterceptor.kt # Token 刷新 ├── NetworkHelper.kt # 安全请求封装 └── model/ └── BaseResponse.kt # 统一响应模型
⚡ 性能优化与调试建议
优化项 | 建议 |
---|---|
⏱️ 超时设置 | 连接 10s,读取 15s,写入 15s |
🧠 缓存策略 | 静态接口可添加本地缓存 |
🔍 日志管理 | Debug 模式启用 BODY,Release 模式关闭 |
♻️ 连接池复用 | 默认 Keep-Alive,可减少握手时间 |
🧩 异常监控 | 在 Result.failure 中上报错误信息 |
🏁 结语
通过这套封装,我们构建了一个高扩展性、高可维护性的网络层:
层级 | 功能 | 示例 |
---|---|---|
通信层 | OkHttp | 超时、缓存、拦截器 |
封装层 | Retrofit | 动态接口映射 |
逻辑层 | 协程 + Result | 异常捕获、安全返回 |
扩展层 | Token、多 BaseUrl | 统一管理 |
🔧 这是一套可以直接落地于实际项目的通用网络架构,既简洁又灵活,适用于 MVVM、MVI 等主流架构。