J'utilise le nouveau Retrofit2 avec suspension des coroutines, et avec les requêtes GET tout fonctionne bien.
Mais je dois maintenant implémenter une requête POST, et je n'arrive pas à la faire fonctionner.
J'ai un exemple CURL qui ressemble à ceci : curl -X POST -H "Content-Type: application/json;charsets: utf-8" -d '{"tx_guapptokenlist_tokenitem":{"tokenchar":"my-token-string","platform":"android"}}' https://www.example-url.com/tokens?type=56427890283537921
Cela fonctionne bien, et renvoie cette réponse : {"errors":false,"success":true}%
Voici donc à quoi ressemble ma requête dans ma classe Api :
@Headers( "Content-Type: application/json" )
@POST("/tokens?type=56427890283537921")
suspend fun sendFirebaseToken(@Body tokenRequest: RequestBody) : Call<TokenResponse>
Voici ma classe TokenResponse :
@JsonClass(generateAdapter = true)
data class TokenResponse(
@Json(name="errors")
val errors: Boolean,
@Json(name="success")
val success: Boolean)
et la classe ApiClient que j'utilise :
object ApiClient {
private const val BASE_URL = "https://myExampleUrl.com"
private var retrofit: Retrofit? = null
var moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val client: Retrofit?
get() {
if (retrofit == null) {
retrofit = Retrofit.Builder().baseUrl(
BASE_URL
).client(getOkHttpClient())
.addConverterFactory(MoshiConverterFactory.create())
.build()
}
return retrofit
}
fun getOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder().addInterceptor(getLoggingInterceptor())
.connectTimeout(120, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS).writeTimeout(90, TimeUnit.SECONDS).build()
}
private fun getLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().setLevel(
if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.HEADERS
else HttpLoggingInterceptor.Level.NONE
)
}
}
La première chose étrange que j'ai remarquée : Même avec le @POST
si mon suspend fun
n'a pas de type de retour, je n'obtiens pas d'erreur, mais okhttp enverra toujours une demande GET (au moins le point de terminaison reçoit toujours un GET). Je ne sais pas si c'est censé être comme ça ?
De toute façon : J'ai besoin des valeurs de retour, donc je retourne Call<TokenResponse>
. Cela m'amène à mon principal problème, que je n'arrive pas à résoudre : Si maintenant j'exécute mon code, il se plante avec ce log :
java.lang.IllegalArgumentException: Unable to create converter for retrofit2.Call<myapp.communication.TokenResponse>
for method TokenApi.sendToken
at retrofit2.Utils.methodError(Utils.java:52)
Pour essayer de résoudre ce problème, j'ai utilisé moshi-kotlin-codegen pour générer l'adaptateur approprié (d'où les annotations dans la classe de données), mais sans succès. La classe est générée, mais n'est pas utilisée. J'ai essayé de passer un Moshi avec JsonAdapterFactory comme ceci var moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
à mon ConverterFactory mais cela ne fonctionne pas non plus. J'ai essayé d'ajouter l'adaptateur généré maually à moshi mais cela ne fonctionne pas non plus.
J'ai également essayé de renvoyer différents types dans ma demande. La documentation de Retrofit indique que sans convertisseur, on ne peut renvoyer qu'un type ResponseBody
mais le résultat est le même : Retrofit se plaint de ne pas avoir de convertisseur. La même chose pour le retour Call<Void>
J'ai l'impression de manquer quelque chose ici ? Qui peut m'aider ? Je suis heureux de fournir plus de détails, veuillez demander ce dont vous avez besoin.