设计网络框架
问题
如何设计一个 Android 客户端网络框架?
答案
分层架构
核心设计
// API 定义层
interface UserApi {
@GET("users/{id}")
suspend fun getUser(@Path("id") id: String): ApiResponse<User>
}
// 统一响应模型
data class ApiResponse<T>(
val code: Int,
val message: String,
val data: T?
)
// 统一结果封装
sealed class Result<out T> {
data class Success<T>(val data: T) : Result<T>()
data class Error(val code: Int, val message: String) : Result<Nothing>()
data class Exception(val e: Throwable) : Result<Nothing>()
}
Token 自动刷新拦截器
class TokenInterceptor(
private val tokenProvider: TokenProvider
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request().newBuilder()
.header("Authorization", "Bearer ${tokenProvider.accessToken}")
.build()
val response = chain.proceed(request)
// 401 时自动刷新 Token 并重试
if (response.code == 401) {
synchronized(this) {
// 双重检查:其他线程可能已经刷新过了
val newToken = tokenProvider.refreshTokenSync()
if (newToken != null) {
response.close()
val retryRequest = request.newBuilder()
.header("Authorization", "Bearer $newToken")
.build()
return chain.proceed(retryRequest)
}
}
}
return response
}
}
网络状态监听
class NetworkMonitor(context: Context) {
private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val isOnline: StateFlow<Boolean> = callbackFlow {
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) { trySend(true) }
override fun onLost(network: Network) { trySend(false) }
}
connectivityManager.registerDefaultNetworkCallback(callback)
// 初始状态
trySend(connectivityManager.activeNetwork != null)
awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
}.stateIn(CoroutineScope(Dispatchers.IO), SharingStarted.Eagerly, true)
}
设计要点
| 要点 | 方案 |
|---|---|
| 统一错误处理 | CallAdapter 将 HTTP 异常转为 Result.Error |
| 请求取消 | 协程取消自动取消 OkHttp Call |
| 离线优先 | OkHttp CacheControl + Room 本地缓存 |
| 重试策略 | OkHttp Interceptor + 指数退避 |
| 日志 | HttpLoggingInterceptor(debug only) |
常见面试问题
Q1: Retrofit 和 OkHttp 的关系?
答案:
OkHttp 是 HTTP 客户端,负责底层的网络请求(连接池、拦截器、缓存等)。Retrofit 是 OkHttp 之上的声明式 API 框架,通过注解和接口定义来简化请求构建、参数序列化、响应反序列化。Retrofit 内部使用 OkHttp 发起实际的 HTTP 请求。两者是上下层关系,不是替代关系。