Get request function overlaod for different Queries - android

I'm new to android development and still learning Kotlin so my question may be simple.
So, what i want to achieve is to have getRequest() function overloaded for multiple Query parameters.
For example this are two of my functions:
#GET("{path}")
fun getRequest(
#Path("path") path: String?,
#Query("country") country : String,
#Query("apiKey") apiKey: String): Call<String>
#GET("{path}")
fun getRequest(
#Path("path") path: String?,
#Query("q") q: String,
#Query("from") from:String,
#Query("to") to: String,
#Query("sortBy") sortBy: String,
#Query("apiKey") apiKey: String): Call<String>
The problem I have is I want to have another getRequest() function with same amount of parameters as the first one So how can I achieve this if the Query parameter has to be different
#GET("{path}")
fun getRequest(
#Path("path") path: String?,
#Query("q") q: String,
#Query("apiKey") apiKey: String): Call<String>

Since the signatures of the methods are the same (same name, and same types of parameters in the same order), the JVM won't let you do this - it can't pick the method to call based on named arguments, those only really exist at the Kotlin language level.
You can either change some of the types (which doesn't seem viable), or use different method names for the different use cases, i.e. getRequestByCountry(), getRequestForQuery(), something like that.

Related

Android kotlin Change field names in class (but also keep the old ones -> be able to switch between them)

I have situation where I have next class:
data class LoginBody(
var username: String,
var password: String,
var deviceType: String,
var deliveryPlatform: String,
var osName: String,
var deviceId: String
)
This class is propagated through all application and is used on various places. I have now demand to implement changes in my data class. It should now look like this:
data class LoginBody(
var username: String,
var password: String,
var device_type: String,
var client_platform: String,
var os_name: String,
var device_id: String
)
But I have to keep both implementations and sometimes when app starts I should use first option and sometimes second.
I can solve this. Creating other class with different name and connecting these 2 classes with interface. After that call interface in all the places in the app where I used to call the class.
In this case it looks like overkill since the first implementation will die immediately after the testing on production is done.
I would like to have nice solution like for example with converting function in my LoginBody data class:
fun LoginBody.convertToNewLoginBody(shouldConvert: Boolean) = ....
But I feel like this solution is impossible. Before starting with implementation that I wrote above, I decided to ask here to see if anyone has idea how to solve it with extension function or with some similar way (if it is actually possible). Thanks in advance!

How to query multiple params like array in retrofit?

I'm trying to translate the next endpoint to an api service endpoint of retrofit, but I didn't found how I need to write the sentence.
The endpoint:
https://balldontlie.io/api/v1/stats?season[]=2018&player_ids[]=237
My try:
#GET("stats/{season}{player_ids")
suspend fun getStatsByPlayerId(#Path("player_ids") playerId: String, #Path("season") season: String): Response<DataNetworkModel>
And advice to fix this? Thank you
For example:
#GET("stats")
suspend fun getStats(
#Query("seasons[]") seasons: List<Int>
): Response<DataNetworkModel>
Calling it this way:
service.getStats(listOf(2015, 2016))
will give you such URL:
https://www.balldontlie.io/api/v1/stats?seasons[]=2015&seasons[]=2016

Identical Retrofit call throws Unable to create call adapter error while the other one works

I am trying to setup Paging 3 with Retrofit and I am unable to get past this call.
val response = redditAPI.getSubreddits(mBearer, mWhere, position, params.loadSize)
The getSubreddits method is this
#GET("/subreddits/mine/{where}")
fun getSubreddits(
#Header("Authorization") bearer: String,
#Path("where") where: String,
#Query("after") after: String,
#Query("count") count: Int
): SubredditResponse
I have checked with a debugger and the inputs are exactly what I want.
A friend implemented this
#GET("{subreddit}/{filter}")
suspend fun getPostList(
#Path("subreddit") subreddit: String,
#Path("filter") filter: String,
#Query("after") after: String,
#Query("count") count: Int,
#Header("Authorization") bearer: String
): Listing
and he used this call
val response = redditAPI.getPostList(mSubreddit, mFilter, position, params.loadSize, mBearer)
and it works perfectly. I read that this error is related to the fact that Call should be used as a return type but that is the way Paging 3 is set up with Retrofit and I can see no reason why it won't work. It's probably something stupid but I really cannot see what it is. The inputs from the other levels above this call are also correct, also checked with a debugger and all seem well.
Thank you in advance.
So, the problem was the missing suspend keyword before declaring the function. The Retrofit error was not helpful at all and I have little experience with Kotlin, so I had no idea the suspend keyword was that important. Lesson learned.

how can i send json data using GET method in Retrofit?

Backend developer gave me API description and that uses GET method and it is JSON format.
I never tried this way and as far as I know it's not possible that sending data in request body. with GET method in retrofit library.
He uses Django. And I tried with Query and Path... And nothing works... Even I tried with no annotation with the parameter.
{
"data": "oicudsfqoerzxddadsdf"
}
1.
#GET("find/data")
fun findData(
#Header("Authorization") sessionId: String,
#Query("data") data: String
): Call<FinderResult>
2.
#GET("find/data")
fun findData(
#Header("Authorization") sessionId: String,
data: String
): Call<FinderResult>
3.
#GET("find/data")
fun findData(
#Header("Authorization") sessionId: String,
dataObj: DataObj
): Call<FinderResult>
#Keep
class DataObj(var data: String){
}
All didn't work. However, It worked on Postman using raw format(should select JSON). How can I use GET request with JSON? what's the problem?
GET method purpose is only to retrieve data from server, not to send data. the only way to send data is using of query parameter in url which it's limitation is 2000 char.
When we want to use query parameter for sending data purpose we should be careful to send well-formed url characters. JSON need to be processed before attaching to URL.
So my advice is using #Query("<name of parameter which is specified by server>") and putting #FormUrlEncoded over findData method.
#FormUrlEncoded
#GET("find/data")
fun findData(
#Header("Authorization") sessionId: String,
#Query("<name of parameter which is specified by server>") data: String
): Call<FinderResult>
For more information look at:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
https://futurestud.io/tutorials/retrofit-send-data-form-urlencoded
https://www.vogella.com/tutorials/Retrofit/article.html

Retrofit - pass two parameters

Link: "www.example.com/getnewcar/?car[color]={colorOfCar}&car[price]={priceOfCar}"
#GET(...)
fun getNewCar(
#Query("car[color]") color: String,
#Query("car[price]") price: String,
...
): Single<JSONApiObject>
I call this function like: b.getNewCar(carColor, carPrice)
URL query string ".." must not have replace block. For dynamic query parameters use #Query. What am I doing wrong? I looked at docs and they suggest using #Query. Can't find what's off tho.
#Query automatically generates the query part of the URL, so your #GET annotation should not include it.
Instead of #GET("www.example.com/getnewcar/?car[color]={colorOfCar}&car[price]={priceOfCar}") it should just be #GET("www.example.com/getnewcar/").

Categories

Resources