Android 网络层最佳实践:Retrofit + OkHttp 封装与实战

📖 目录

  1. 前言

  2. [为什么要封装 Retrofit + OkHttp](#为什么要封装 Retrofit + OkHttp)

  3. 基础封装思路

  4. [支持多 BaseUrl 的设计](#支持多 BaseUrl 的设计)

  5. 统一响应模型与错误处理

  6. [Token 自动刷新机制](#Token 自动刷新机制)

  7. 完整网络层结构

  8. 性能优化与调试建议

  9. 结语


💬 前言

在 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 等主流架构。

相关推荐
00后程序员张17 小时前
iOS 上架费用全解析 开发者账号、App 审核、工具使用与开心上架(Appuploader)免 Mac 成本优化指南
android·macos·ios·小程序·uni-app·cocoa·iphone
来来走走17 小时前
Android开发(Kotlin) 扩展函数和运算符重载
android·开发语言·kotlin
wuwu_q17 小时前
用通俗易懂 + Android 开发实战的方式,详细讲解 Kotlin Flow 中的 retryWhen 操作符
android·开发语言·kotlin
天选之女wow18 小时前
【代码随想录算法训练营——Day60】图论——94.城市间货物运输I、95.城市间货物运输II、96.城市间货物运输III
android·算法·图论
沐怡旸18 小时前
【底层机制】Android对Linux线程调度的移动设备优化深度解析
android·面试
li-jia-wei19 小时前
我在造一个编程语言,叫 Free
kotlin
正经教主20 小时前
【咨询】Android Studio 第三方手机模拟器对比【202511】
android·ide·android studio
Jomurphys20 小时前
网络 - 缓存
android
似霰21 小时前
安卓14移植以太网&&framework-connectivity-t 编译问题
android·framework·安卓·ethernet