Android网络请求Retrofit和Okhttp封装与优化指南

在Android开发中,Retrofit和OkHttp是网络请求的核心库。以下是如何高效封装它们的详细步骤:

一、基础封装方案

1. 添加依赖
dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.okhttp3:okhttp:4.9.3'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
}
2. OkHttp封装
object OkHttpManager {
    private const val CACHE_SIZE = 10 * 1024 * 1024L // 10MB
    private var okHttpClient: OkHttpClient? = null

    fun getClient(context: Context): OkHttpClient {
        return okHttpClient ?: createClient(context).also { okHttpClient = it }
    }

    private fun createClient(context: Context): OkHttpClient {
        val cache = Cache(File(context.cacheDir, "http_cache"), CACHE_SIZE)

        return OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .cache(cache)
            .addInterceptor(LoggingInterceptor())
            .addInterceptor(AuthInterceptor())
            .addNetworkInterceptor(CacheInterceptor())
            .build()
    }
}

class LoggingInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        // 日志输出逻辑
        return chain.proceed(request)
    }
}

class AuthInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request().newBuilder()
            .addHeader("Authorization", "Bearer ${getToken()}")
            .build()
        return chain.proceed(request)
    }
}

class CacheInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        var request = chain.request()
        if (!isNetworkAvailable()) {
            request = request.newBuilder()
                .cacheControl(CacheControl.FORCE_CACHE)
                .build()
        }
        return chain.proceed(request).newBuilder()
            .removeHeader("Pragma")
            .header("Cache-Control", "public, max-age=${60 * 60}") 
            .build()
    }
}
3. Retrofit封装
object RetrofitManager {
    private val retrofitMap = mutableMapOf<String, Retrofit>()

    fun <T> createService(
        context: Context,
        serviceClass: Class<T>,
        baseUrl: String = BASE_URL
    ): T {
        val retrofit = retrofitMap[baseUrl] ?: buildRetrofit(context, baseUrl)
        return retrofit.create(serviceClass)
    }

    private fun buildRetrofit(context: Context, baseUrl: String): Retrofit {
        return Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(OkHttpManager.getClient(context))
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(CoroutineCallAdapterFactory())
            .build()
            .also { retrofitMap[baseUrl] = it }
    }
}
4. API Service定义
interface UserService {
    @GET("users/{id}")
    suspend fun getUser(@Path("id") userId: String): Response<User>

    @POST("users")
    suspend fun createUser(@Body user: User): Response<BaseResponse>
}

二、高级封装技巧

1. 统一响应处理
sealed class ApiResult<out T> {
    data class Success<out T>(val data: T) : ApiResult<T>()
    data class Error(val code: Int, val message: String?) : ApiResult<Nothing>()
    object NetworkError : ApiResult<Nothing>()
}

suspend fun <T> safeApiCall(block: suspend () -> Response<T>): ApiResult<T> {
    return try {
        val response = block()
        if (response.isSuccessful) {
            ApiResult.Success(response.body()!!)
        } else {
            ApiResult.Error(response.code(), response.message())
        }
    } catch (e: IOException) {
        ApiResult.NetworkError
    } catch (e: Exception) {
        ApiResult.Error(-1, e.message)
    }
}
2. Repository层封装
class UserRepository {
    private val service = RetrofitManager.createService(
        context = App.context,
        serviceClass = UserService::class.java
    )

    suspend fun getUser(userId: String): ApiResult<User> {
        return safeApiCall { service.getUser(userId) }
    }
}
3. ViewModel集成
class UserViewModel : ViewModel() {
    private val repository = UserRepository()
    private val _userData = MutableStateFlow<ApiResult<User>>(ApiResult.Success(null))
    val userData: StateFlow<ApiResult<User>> = _userData

    fun fetchUser(userId: String) {
        viewModelScope.launch {
            _userData.value = repository.getUser(userId)
        }
    }
}

三、关键配置项

  1. 多域名管理
object ApiConfig {
    const val MAIN_API = "https://api.main.com/"
    const val PAYMENT_API = "https://api.payment.com/"
}

// 使用方式
val paymentService = RetrofitManager.createService(
    context, 
    PaymentService::class.java,
    ApiConfig.PAYMENT_API
)
  1. 动态Header处理
class DynamicHeadersInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val original = chain.request()
        val requestBuilder = original.newBuilder()
            .header("App-Version", BuildConfig.VERSION_NAME)
            .header("Device-Type", "Android")
        
        // 动态添加token
        getAuthToken()?.let {
            requestBuilder.header("Authorization", "Bearer $it")
        }
        
        return chain.proceed(requestBuilder.build())
    }
}
  1. 文件上传下载
interface FileService {
    @Multipart
    @POST("upload")
    suspend fun uploadFile(@Part file: MultipartBody.Part): Response<UploadResponse>

    @Streaming
    @GET("files/{filename}")
    suspend fun downloadFile(@Path("filename") name: String): Response<ResponseBody>
}

四、调试技巧

  1. Stetho集成
implementation 'com.facebook.stetho:stetho-okhttp3:1.6.0'
OkHttpClient.Builder()
    .addNetworkInterceptor(StethoInterceptor())
    .build()
  1. Mock数据调试
val mockClient = OkHttpClient.Builder()
    .addInterceptor(MockInterceptor())
    .build()

class MockInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        return when (chain.request().url.pathSegments.last()) {
            "users" -> mockUsersResponse()
            else -> chain.proceed(chain.request())
        }
    }
}

五、性能优化建议

  1. 连接池配置
val connectionPool = ConnectionPool(
    maxIdleConnections = 5,
    keepAliveDuration = 5, 
    timeUnit = TimeUnit.MINUTES
)

OkHttpClient.Builder()
    .connectionPool(connectionPool)
  1. DNS优化
class CustomDns : Dns {
    override fun lookup(hostname: String): List<InetAddress> {
        return try {
            Dns.SYSTEM.lookup(hostname)
        } catch (e: Exception) {
            InetAddress.getAllByName(hostname).toList()
        }
    }
}
  1. 响应缓存策略
val cacheControl = CacheControl.Builder()
    .maxAge(2, TimeUnit.HOURS)
    .maxStale(3, TimeUnit.DAYS)
    .build()

request.newBuilder()
    .cacheControl(cacheControl)
    .build()

这种封装方案提供了以下优势:

  • 统一的网络配置管理
  • 完善的错误处理机制
  • 支持协程和响应式编程
  • 灵活的缓存策略
  • 便捷的多域名支持
  • 完整的日志监控能力

实际使用中可根据项目需求灵活调整拦截器配置、缓存策略以及错误处理逻辑。建议配合Hilt等依赖注入框架实现更好的组件管理。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值