La plupart des applications mobiles consomment des API REST JSON pour récupérer toutes les données nécessaires à leur fonctionnement.
Retrofit est aujourd’hui une des façons les plus simples d’implémenter des appels à des webservices REST.
Il s’agit d’un client REST développé par Jake Wharton ainsi que l’ensemble du staff de Square. Cette librairie est basée elle-même sur le client RESTREST (REpresentational State Transfer) est un style d'architecture logicielle qui fonctionne sous un certain nombre de contraintes. OKHttp (développée encore par Square !) et permet d’implémenter plus facilement et rapidement des requêtes réseau sur Android (Java ou Kotlin).
Retrofit nous évite ainsi d’installer manuellement toutes les parties nécessaires à l’exécution d’une requête, comme par exemple la gestion des réponses JSON ou la création d’une AsyncTask.
Cela permet un gain de temps conséquent et un code plus clair pour des performances équivalentes.
Depuis, Retrofit 2.6 supporte l’utilisation des coroutines. Cela permet de ne plus utiliser de callback ou la fonction enqueue.
Pour cet exemple, nous utiliserons https://jsonplaceholder.typicode.com/, qui est une APIUne API est un programme permettant à deux applications distinctes de communiquer entre elles et d’échanger des données. gratuite fournissant des données de test.
La permission « INTERNET » est requise pour appeler des APIs dans une application AndroidAndroid est un système d'exploitation mobile basé sur Linux..
« ACCES_NETWORK_STATE » permet d'identifier l'état de la connexion internet de l'appareil.
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
Pour installer Retrofit, il faut au minimum Java 8 + ou Android API 21 +.
Vous aurez ensuite besoin d’installer les dépendances suivantes en les renseignant dans le fichier build.gradle sous « dependencies ».
//Retrofit
implementation ’com.squareup.retrofit2:retrofit:2.9.0’
implementation ’com.squareup.retrofit2:converter-gson:2.9.0’
//Coroutine
implementation ’org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5’
implementation ’org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5’
Le client Retrofit doit être configuré avec une URLUniform Ressource Locator serveur (BASE_URL) ainsi qu’un convertisseur de requêtes. Ce convertisseur va permettre de convertir automatiquement la réponse JSON en objets. Ici, nous utilisons le convertisseur Gson. Il ne faut pas oublier le mot clé lazy, afin de ne pas dupliquer des instances de Retrofit.
package com.example.myapplication
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object ApiClient {
private const val BASE_URL: String = "https://jsonplaceholder.typicode.com/"
private val gson : Gson by lazy {
GsonBuilder().setLenient().create()
}
private val httpClient : OkHttpClient by lazy {
OkHttpClient.Builder().build()
}
private val retrofit : Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
}
val apiService : ApiService by lazy{
retrofit.create(ApiService::class.java)
}
}
On retrouve, sous forme d’annotations, la méthode et la route. Il faudra aussi spécifier le type de réponse afin que Gson puisse la désérialiser.
On remarquera la nécessité de préciser le type de paramètre avec les annotations @Path, @Query et @Body
package com.example.myapplication
import com.example.myapplication.models.Comment
import com.example.myapplication.models.Post
import com.example.myapplication.models.User
import retrofit2.Response
import retrofit2.http.*
interface ApiService {
@GET("users")
suspend fun getUsers(): Response<MutableList<User>>
@GET("posts/{num}")
suspend fun getPostById(@Path("num") num : Int): Response<Post>
@GET("comments")
suspend fun getCommentsByPost(@Query("postId") postId : Int): Response<MutableList<Comment>>
@POST("posts")
suspend fun createPost(@Body post: Post): Response<Post>
}
Les méthodes suivantes sont disponibles :
L’annotation @HEADER est aussi disponible ici pour définir un ou plusieurs headers sur un endpoint.
Ici, nous créons les modèles via des data classes afin de désérialiser les réponses et de stocker nos données. Point important, chaque champ de chaque modèle doit être identique à la réponse (nom et type) afin que la désérialisation de cette dernière fonctionne.
package com.example.myapplication.models
data class User(
val id: Int? = null,
val name: String? = null,
val userName: String? = null,
val email: String? = null,
val address : Address? = null,
val phone: String? = null,
val website: String? = null
)
package com.example.myapplication.models
data class Address(
val street: String? = null,
val suite: String? = null,
val city: String? = null,
val zipCode: String? = null
)
package com.example.myapplication.models
data class Comment (
val postId: Int = 0,
val id: Int = 0,
val name: String? = null,
val email: String? = null,
val body: String? = null
)
package com.example.myapplication.models
data class Post (
val userId: Int = 0,
val id: Int? = null,
val title: String? = null,
val body: String? = null
)
Pour cette partie, nous utiliserons Coroutine. Coroutine est un utilitaire de KotlinLangage de programmation permettant de développement des applications mobiles Android natives. permettant d’effectuer des tâches asynchrones. Pour cela, nous devons implémenter CoroutineScope qui indiquera où la coroutine devra envoyer les données. Ici, pour cet exemple, ce sera dans MainScope si l’on veut modifier l’affichage de la mainActivity.
Commençons par créer une nouvelle coroutine avec la fonction launch et la restreindre au main thread avec Dispachers.Main.
Le try/catch est là pour remonter les erreurs du client.
Une dernière vérification de la validité de la réponse et vous pourrez utiliser le body pour vos fonctionnalités !
private fun executeCall() {
launch(Dispatchers.Main) {
try {
val response = ApiClient.apiService.getPostById(1)
if (response.isSuccessful && response.body() != null) {
val content = response.body()
//do something
} else {
Toast.makeText(
this@MainActivity,
"Error Occurred: ${response.message()}",
Toast.LENGTH_LONG
).show()
}
} catch (e: Exception) {
Toast.makeText(
this@MainActivity,
"Error Occurred: ${e.message}",
Toast.LENGTH_LONG
).show()
}
}
}
Et voilà ! Vous savez désormais comment implémenter Retrofit dans un projet Android via Kotlin ! À vous le gain de temps, le code plus clair et tout aussi performant.
À très bientôt pour de nouveaux articles Android !
Créer une application mobile, c’est s’adapter à son environnement
Qui n’a jamais eu le besoin de comparer 2 schemas de base de données Mysql après avoir oublier de noter l’ensemble des modifications apportées à un environnement ?
Découvrez la planche #64 !