Retrofit发起请求前如何获取含动态路径、查询参数的最终请求URL?
Retrofit 提前获取最终拼接URL的实现方案
不需要自行封装端点构建包装类,Retrofit 生态原生提供两种成熟方案可以满足需求:
方案1:OkHttp 应用拦截器(优先推荐,全量请求无侵入处理)
直接在 OkHttp 拦截器链最前端添加自定义应用拦截器,此处可以直接获取到 Retrofit 已经拼接完成的完整 URL,优先做缓存校验,命中后直接返回缓存响应无需发起网络请求:
class CachePreCheckInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request() // 直接获取完整拼接后的URL,包含路径参数、查询参数 val fullRequestUrl = request.url.toString() // 校验数据库是否存在该URL的缓存 val cacheContent = yourDatabase.queryCacheByUrl(fullRequestUrl) if (cacheContent != null) { // 命中缓存直接构造响应返回,不会触发后续网络请求 return Response.Builder() .request(request) .protocol(Protocol.HTTP_1_1) .code(200) .message("Cache Hit") .body(cacheContent.toResponseBody("application/json".toMediaType())) .build() } // 未命中则继续执行请求,原有响应拦截器的缓存逻辑无需修改 return chain.proceed(request) } }
使用时将该拦截器添加到 OkHttpClient 配置中即可:
val okHttpClient = OkHttpClient.Builder() .addInterceptor(CachePreCheckInterceptor()) // 注意用addInterceptor,不是addNetworkInterceptor // 其他原有配置 .build()
方案2:业务层主动构建URL(适合需要提前拿到URL做自定义逻辑的场景)
如果需要在调用 Retrofit 接口方法之前,就在业务代码中拿到完整URL,可以基于 Retrofit 绑定的 BaseUrl 配合 OkHttp 的 HttpUrl 工具类构建,不需要手动处理拼接规则:
fun buildFinalRequestUrl( retrofit: Retrofit, apiPath: String, pathParams: Map<String, String>, queryParams: Map<String, String> ): String { // 替换路径占位符 var processedPath = apiPath pathParams.forEach { (key, value) -> processedPath = processedPath.replace("{$key}", value) } // 基于Retrofit的BaseUrl构造完整地址 val urlBuilder = requireNotNull(retrofit.baseUrl.newBuilder(processedPath)) { "API路径和BaseUrl不匹配" } // 添加查询参数 queryParams.forEach { (key, value) -> urlBuilder.addQueryParameter(key, value) } return urlBuilder.build().toString() }
对应你的接口调用示例:
val finalUrl = buildFinalRequestUrl( retrofit = yourRetrofitInstance, apiPath = USER_DETAIL, pathParams = mapOf(Params.USER_NAME to "目标用户名"), queryParams = mapOf(NetworkConstants.Params.LANG to "zh-CN") ) // 拿到URL后可先做缓存校验,再决定是否发起接口请求
内容的提问来源于stack exchange,提问作者Ahmad Shahwaiz
相关产品推荐
相关产品推荐

