Android 网络层最佳实践:Retrofit + OkHttp 封装与实战
📖 目录
-
前言
-
为什么要封装 Retrofit + OkHttp
-
基础封装思路
-
支持多 BaseUrl 的设计
-
统一响应模型与错误处理
-
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
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)// 如果请求头中包含自定义 BaseUrlif (!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
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()}
}
使用示例:
val userApi = RetrofitManager.getService().create(UserApi::class.java)
val payApi = RetrofitManager.getService("https://pay.api.example.com/").create(PayApi::class.java)
🧩 统一响应模型与错误处理
1. 定义统一返回结构
data class BaseResponse<T>(val code: Int,val msg: String?,val data: T?
) {fun isSuccess() = code == 200
}
2. 安全请求封装(协程版)
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 调用示例
class LoginViewModel : ViewModel() {private val _loginState = MutableLiveData<Result<LoginResponse>>()val loginState: LiveData<Result<LoginResponse>> = _loginStatefun login(username: String, password: String) {viewModelScope.launch {val result = safeApiCall {RetrofitManager.getService().create(UserApi::class.java).login(username, password)}_loginState.value = result}}
}
🔑 Token 自动刷新机制
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 等主流架构。