使用不同的路径参数更新@url 路径

Update @url path with different path parameters

Android - retrofit 2.9.0

我有以下改造方法。我正在使用 @Url 来包含基础 url 和搜索产品的路径。但是,我需要将 code 作为路径的一部分传递。因为我需要包含完整路径,所以如何将代码添加到完整的 url 路径中?

"https://myBaseUrl/v2/products/{code}/search"

@GET
fun searchProductV2(
    @Path("code") storeCode: String,
    @Url fullPath: String = "https://myBaseUrl/v2/products/{code}/search",
    @Query("searchCriteria[pageSize]") pageSize: String,
    @QueryMap apiSearchCriteria: Map<String, String>,
    @HeaderMap headerMap: Map<String, String> = emptyMap()
): Single<Products>

似乎是显而易见且简单的解决方案...

@Url fullPath: String = "https://myBaseUrl/v2/products/" +storeCode+ "/search",

使用 @GET 注释定义 URL 模板
...然后替换为 @Path 注释:

@GET("{baseUrl}products/{storeCode}/search")
fun searchProductV2(
    @Path("baseUrl") baseUrl: String = "https://myBaseUrl/v2/",
    @Path("storeCode") storeCode: String = "default",
    ...
): Single<Products>

这里也可以传递常量值:

@GET(Constants.API_BASE_URL_V2 + "products/{storeCode}/search")
fun searchProductV2(
    @Path("storeCode") storeCode: String = "default",
    ...
): Single<Products>

或者只是版本 v2,假设 BASE_URLhttps://myBaseUrl/。无论这些如何组合,都必须是 String、常量值或 @Path,不允许其他任何内容:

@GET(Constants.API_VERSION_V2 + "/products/{storeCode}/search")
fun searchProductV2(
    @Path("storeCode") storeCode: String = "default",
    ...
): Single<Products>

总的来说,没有别的办法。这是因为没有参数可以用作另一个参数的替代。此代码不是 运行,而只是 interface 定义,从中生成相应的 运行time 类 - 这就是尝试添加自定义代码的原因毫无意义。

不确定 Single<Products> 是什么,但默认(未映射/原始)return 类型是 Java 中的 Call<ResponseBody>。用于 ORM 的模型 class/es(带有 GSON 或 Moshi 转换器)可以使用 @SerializedName() 映射字段名称。

您尝试的方法不会起作用,因为如果您指定 @Url,它需要静态 URL,它不会考虑 @Path

解决方案 1

删除@Path参数,只发送@Url中的格式化字符串。

您的方法声明将如下所示:

@GET
fun searchProductV2(
    @Url fullPath: String,
    @Query("searchCriteria[pageSize]") pageSize: String,
    @QueryMap apiSearchCriteria: Map<String, String>,
    @HeaderMap headerMap: Map<String, String> = emptyMap()
): Single<Products>

你的fullPath参数可以这样初始化:

val fullPath = "https://myBaseUrl/v2/products/%s/search".format("storeCode")

解决方案 2

更好的方法是使用String作为@Url参数。 (@Url 可以是 okhttp3.HttpUrlStringjava.net.URIandroid.net.Uri

这是一个使用 android.net.Uri 的例子:

您的方法声明将如下所示:

@GET
fun searchProductV2(
    @Url fullPath: Uri,
    @Query("searchCriteria[pageSize]") pageSize: String,
    @QueryMap apiSearchCriteria: Map<String, String>,
    @HeaderMap headerMap: Map<String, String> = emptyMap()
): Single<Products>

你的fullPath参数可以这样初始化:

val fullPath = Uri.parse("https://myBaseUrl/v2/products/%s/search".format("storeCode"))

为了让这段代码更漂亮,你可以创建一个助手 class:

class DynamicUrl(private val formatString: String, private vararg val args: Any?) {
    fun toUri(): Uri = Uri.parse(formatString.format(*args))
}

现在您的 fullPath 参数可以像这样初始化:

val fullPath = DynamicUrl("https://myBaseUrl/v2/products/%s/search", "storeCode").toUri()