Search code examples
androidretrofit2

Update @url path with different path parameters


Android - retrofit 2.9.0

I have the following retrofit method. I am using the @Url to include the base url and the path to search for products. However, I need to pass a code as part of the path. As I need to include the fullpath how can I add the code into the full url path?

"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>

Solution

  • What you are trying won't work because if you specify @Url, it expects a static URL, it won't take @Path into consideration.

    Solution 1

    Remove the @Path parameter and just send the formatted string in @Url.

    your method declaration will look like this:

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

    and your fullPath parameter can be initialized like this:

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

    Solution 2

    A better approach would be to not use String as the @Url parameter. (@Url can be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri)

    Here's an example using android.net.Uri:

    your method declaration will look like this:

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

    and your fullPath parameter can be initialized like this:

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

    To make this code more nicer, you can create a helper class:

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

    and now your fullPath parameter can be initialized like this:

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