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>
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()
Define the URL template with the @GET annotation
... and then substitute with the @Path annotation:
@GET("{baseUrl}products/{storeCode}/search")
fun searchProductV2(
@Path("baseUrl") baseUrl: String = "https://myBaseUrl/v2/",
@Path("storeCode") storeCode: String = "default",
...
): Single<Products>
Passing a constant value is also possible there:
@GET(Constants.API_BASE_URL_V2 + "products/{storeCode}/search")
fun searchProductV2(
@Path("storeCode") storeCode: String = "default",
...
): Single<Products>
Or just the version v2, assuming a BASE_URL of https://myBaseUrl/. No matter how these are being combined, it needs to be a String, a constant value or a @Path, nothing else is permitted:
@GET(Constants.API_VERSION_V2 + "/products/{storeCode}/search")
fun searchProductV2(
@Path("storeCode") storeCode: String = "default",
...
): Single<Products>
Generally speaking, there is no other way. This is because no parameter can be used as a substitution for another one parameter. This code doesn't run, but is only the interface definition, from which the corresponding runtime classes are being generated from - that's why trying to add custom code is pointless.
Not sure what Single<Products> is, but the default (unmapped / raw) return type would be Call<ResponseBody> in Java. The model class/es used for ORM (with GSON or Moshi converter) can use @SerializedName() to map the field names.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With