Retrofit2+Hilt实现带动态URL的POST请求报错求助
错误原因
这个报错是Retrofit的硬性规则限制:如果接口方法的参数使用了@Url注解,对应方法上的HTTP请求注解(比如@POST、@GET)的括号内必须留空,不能填写任何路径片段。
当前代码里@POST("{id}")写了路径占位符,和参数里的@Url直接冲突,才会触发这个错误。另外代码还存在两个逻辑问题:
@POST里的{id}是路径占位符,和参数里写的@Query("id")作用完全不同:前者是URL路径的一部分,后者是拼接在?后的查询参数,重复定义没有意义。- 动态查询参数如果数量、字段不固定,单独写
@Query灵活性很差。
解决方法
根据实际的动态URL需求,二选一即可:
场景1:需要使用完全自定义的完整请求URL(跨域名、和baseUrl无关的地址)
直接修改接口定义,@POST注解后留空,动态查询参数用@QueryMap承载:
@POST // 注意:这里绝对不能写任何路径内容 suspend fun getConfiguration( @Url fullUrl: String, // 传入完整请求地址,比如"https://custom-domain.com/api/config" @Body configRequest: ConfigRequest, @QueryMap dynamicQueries: Map<String, @JvmSuppressWildcards Any> = emptyMap() ): Config
调用示例:
// 动态组装查询参数,不需要提前固定字段 val queryParams = mapOf( "id" to "config_001", "ts" to System.currentTimeMillis(), "client" to "android" ) val result = api.getConfiguration( fullUrl = "https://your-custom-domain.com/api/xxx", configRequest = ConfigRequest(param1 = "test"), dynamicQueries = queryParams )
Retrofit会自动把@QueryMap里的键值对拼接到URL的查询参数段,不需要手动处理URL拼接。参数里的@JvmSuppressWildcards是为了避免Kotlin类型擦除导致Retrofit识别失败的问题,必须加上。
场景2:仅需要动态拼接baseUrl后的相对路径(不换域名)
这种场景完全不需要用@Url,直接用@Path注解处理动态路径即可,现有Hilt提供Retrofit实例的代码不需要做任何修改:
@POST("{dynamicPath}") suspend fun getConfiguration( @Path("dynamicPath", encoded = true) relativePath: String, // 传入相对路径,比如"config/get" @Body configRequest: ConfigRequest, @QueryMap dynamicQueries: Map<String, @JvmSuppressWildcards Any> = emptyMap() ): Config
@Path的encoded = true参数表示如果传入的路径已经做过URL编码,Retrofit不会重复编码,避免特殊字符导致路径错误。
内容的提问来源于stack exchange,提问作者Pointyhat
相关产品推荐
相关产品推荐

