Faire une requête HTTP GET avec Retrofit en Kotlin Android [AK 9 HTTPS]
Ce tutoriel va te donner les clés pour faire une requête HTTPS GET au format JSON, en Android, avec la bibliothèque Retrofit V2, sous le langage Kotlin.
Concrètement, nous allons demander une liste de pays à un serveur web, REST Countries APIs, en suivant les étapes suivantes :
- Importer Retrofit et Moshi dans le projet Android
- Créer la classe Kotlin représentant les données (à récupérer du serveur)
- Créer l’interface Kotlin représentant l’API du serveur
- Créer l’instance du client Retrofit (en version 2)
- Créer l’instance du service d’API
- Créer la requête GET
- Exécuter la requête GET
- Récupérer le résultat de la requête
Importer Retrofit et Moshi dans le projet Android
Tout d’abord, il faut au préalable importer, dans le projet Android, la dépendance Retrofit 2, ainsi qu’un convertisseur de requête :
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-moshi:$moshi_version"
avec :
ext.retrofit_version = '2.9.0'
ext.moshi_version = '2.9.0'
Il s’agit aussi d’ajouter la permission internet, dans le fichier Manifest :
<uses-permission android:name="android.permission.INTERNET" />
Note : la bibliothèque OkHttp est utilisé pour écrire et lire les sockets par Retrofit V2.
Pour plus de détail, consultez l’article Configurer un projet Android pour utiliser Retrofit.
Dans la suite, nous nous intéressons à réaliser une requête HTTPS GET et à récupérer une liste d’objets au format JSON depuis un serveur distant.
Créer la classe Kotlin représentant les données
Il s’agit de créer la classe Kotlin représentant l’objet à récupérer du serveur.
Par exemple, nous souhaitons récupérer une liste des pays, depuis le serveur Countries APIs. La requête permettant d’obtenir la liste de pays est https://restcountries.com/v3.1/all. En utilisant Postman, il est possible d’analyser le résultat JSON de cette requête :
[
{
"name": {
"common": "Barbados",
"official": "Barbados",
"nativeName": {
"eng": {
"official": "Barbados",
"common": "Barbados"
}
}
},
"tld": [
".bb"
],
"cca2": "BB",
"ccn3": "052",
"cca3": "BRB",
"cioc": "BAR",
"independent": true,
"status": "officially-assigned",
"unMember": true,
"currencies": {
"BBD": {
"name": "Barbadian dollar",
"symbol": "$"
}
},
"idd": {
"root": "+1",
"suffixes": [
"246"
]
},
"capital": [
"Bridgetown"
],
"altSpellings": [
"BB"
],
"region": "Americas",
"subregion": "Caribbean",
"languages": {
"eng": "English"
},
"translations": {
"ara": {
"official": "باربادوس",
"common": "باربادوس"
},
"bre": {
"official": "Barbados",
"common": "Barbados"
},
"ces": {}
}
}
]
Ainsi le serveur, renvoie une liste de pays, contenant :
- un objet (name) lui même contenant
- un nom (common)
Afin de modéliser un tel objet, soit Country, il faut créer les classes Kotlin
correspondant à la réponse du serveur. Par exemple, la classe Country
représente un pays et
CountryDetail
les détails du pays, selon les données du serveur :
data class Country(val name: CountryDetail)
data class CountryDetail(val common: String)
Les attributs du constructeur doivent porter les mêmes noms que ceux du fichier JSON renvoyé par le serveur : name et common. Pour le moment, seulement ces deux attributs nous intéresse, c’est pourquoi les autres n’apparaissent pas dans la classe.
Créer l’interface Kotlin représentant l’API
Il s’agit de créer l’interface Kotlin contenant la déclaration des
requêtes disponibles sur Countries APIs.
Pour le moment, nous avons une seule requête GET, ne prenant aucun paramètre
et renvoyant une liste de pays.
Par exemple, l’interface CountriesService
représente l’API du serveur de cours :
interface CountriesService {
@GET("/v3.1/all")
fun listCountries(): Call<List<Country>>
}
Avec les importations suivants :
import retrofit2.Call
import retrofit2.http.GET
L’annotation @GET
de Retrofit 2 indique la déclaration d’une requête GET.
Ensuite, en paramètre, il est placé le chemin de la requête /v3.1/all
.
La signature de la fonction associé à la requête porte le nom listCountries
(son nom n’a pas d’importance). Elle ne prend pas de paramètre puisque la requête n’en demande pas.
Et elle renvoie un Call<...>
, c’est la réponse du serveur, prenant entre chevron
List<Country>
, c’est-à-dire la liste de pays renvoyée par le serveur au format JSON.
Toutes fonctions associées à une requête, retourne un objet Call<>
, ensuite
le paramètre entre chevron varie selon ce que renvoie le serveur (une liste ou un objet)
et ce que l’on souhaite récupérer. Par ailleurs, si la requête requiert un paramètre
tel qu’un nom d’utilisateur alors il est spécifié en paramètre de la fonction.
Par exemple pour récupérer la liste des répertoires d’un utilisateur GitHub, selon leur API, il faudrait coder en Kotlin :
@GET("/users/{user}/repos")
listRepos(@Path("user") user: String): Call<List<Repo>>
Créer l’instance du client Retrofit
Depuis, une Activity ou bien un
Fragment, nous allons créer une instance de client Retrofit.
Par exemple, dans un Fragment NetworkFragment
:
val retrofit = Retrofit.Builder()
.baseUrl(URL_COUNTRY_API)
.addConverterFactory(MoshiConverterFactory.create())
.build()
avec l’url :
companion object {
const val URL_COUNTRY_API = "https://restcountries.com/"
}
les imports concernés sont celui de Retrofit 2 et de Moshi, le convertisseur de JSON :
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
Le client Retrofit est à configurer avec une url de serveur ainsi qu’un convertisseur de requête. Ici, il est choisi le convertisseur Moshi car il permet de convertir du JSON en objet Kotlin.
Créer l’instance du service
Après avoir créé l’instance du client Retrofit, à la suite dans NetworkFragment
, il s’agit de créer
l’instance du service comme suit :
val service = retro.create(CountriesService::class.java)
et d’importer la classe CountriesService
.
Ce service est créé à partir du client Retrofit, lequel contient l’url du serveur,
et à partir du .class
de l’interface, laquelle contient toutes les requêtes possibles
avec le serveur.
Créer la requête GET
Toujours à la suite dans NetworkFragment
, il s’agit de créer la requête GET :
val countryRequest = service.listCountries()
Exécuter la requête GET
Enfin, il est possible d’exécuter la requête venant d’être créée via la fonction enqueue(object: Callback<…>) de Retrofit :
countryRequest.enqueue(object : Callback<List<Country>> {
override fun onResponse(call: Call<List<Country>>, response: Response<List<Country>>) {
val allCountry = response.body()
for (c in allCountry!!)
Log.v(
MainActivity::class.simpleName,
"NAME: ${c.name.common} \n "
)
}
override fun onFailure(call: Call<List<Country>>, t: Throwable) {
Log.i(MainActivity::class.simpleName, "RETRY AND GOOD LUCK.")
}
})
les importations associées sont les suivantes :
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
ainsi que l’import de la classe Country
.
La fonction enqueue(object: Callback<…>) prend en
paramètre l’objet Callback,
cet objet intercepte la réponse du serveur.
Cette dernière est traitée dans la sur-implémentation des fonctions onResponse(...)
et onFailure(...)
.
Les paramètres du Callback ainsi que des fonctions
onResponse(...)
et onFailure(...)
dépendent directement du type de retour
de la fonction représentant la requête. Dans notre cas, le type de retour de
listCountries()
est List<Country>
(définit par ce que renvoie le serveur).
Récupérer le résultat de la requête
Enfin, la liste des pays en contenu dans response.body()
.
Le code correspondant peut être téléchargé dans le thème “Communication HTTPS” de l’application “Kotlin pour Android : Quiz”.
Finalement, dans cet article nous avons vu comment :
- Importer Retrofit et Moshi dans le projet Android
- Créer la classe Kotlin représentant les données à récupérer du seveur
- Créer l’interface Kotlin représentant l’API du serveur
- Créer l’instance du client Retrofit en version 2
- Créer l’instance du service d’API
- Créer la requête GET
- Exécuter la requête GET
- Récupérer le fruit de la requête
Références
Partagez ou réagissez sur Twitter.
Vous avez trouvé une erreur ou voulez améliorer cet article ? Editez le directement !