Retrofit est un client HTTP de type sécurisé pour Android et Java. Retrofit facilite la connexion à un service Web REST en traduisant l'API en interfaces Java. Dans ce tutoriel, je vais vous montrer comment utiliser l'une des bibliothèques HTTP les plus populaires et les plus recommandées disponibles pour Android..
Cette puissante bibliothèque facilite la consommation de données JSON ou XML, qui sont ensuite analysées dans des objets POJO (Plain Old Java Objects).. OBTENIR
, POSTER
, METTRE
, PIÈCE
, et EFFACER
les demandes peuvent toutes être exécutées.
Comme la plupart des logiciels open-source, Retrofit s’est construit sur d’autres bibliothèques et outils puissants. Retrofit utilise en arrière plan OkHttp (du même développeur) pour gérer les requêtes réseau. De plus, Retrofit n’a pas de convertisseur JSON intégré pour analyser des objets JSON en objets Java. Au lieu de cela, il prend en charge les bibliothèques de conversion JSON suivantes pour gérer cela:
com.squareup.retrofit: convertisseur-gson
com.squareup.retrofit: convertisseur-jackson
com.squareup.retrofit: convertisseur-moshi
Pour les tampons de protocole, Retrofit prend en charge:
com.squareup.retrofit2: converter-protobuf
com.squareup.retrofit2: convertisseur de fil
Et pour XML, Retrofit prend en charge:
com.squareup.retrofit2: convertisseur-simpleframework
Le développement de votre propre bibliothèque HTTP sécurisée pour une interface avec une API REST peut s'avérer une tâche ardue: vous devez gérer de nombreuses fonctionnalités telles que l'établissement de connexions, la mise en cache, la réessai de demandes échouées, le threading, l'analyse des réponses, la gestion des erreurs, etc. La modernisation, en revanche, est très bien planifiée, documentée et testée - une bibliothèque testée au combat qui vous fera gagner un temps précieux et des maux de tête..
Dans ce didacticiel, je vais expliquer comment utiliser Retrofit 2 pour gérer les demandes réseau en construisant une application simple pour interroger des réponses récentes à partir de l'API Stack Exchange. Nous allons effectuer OBTENIR
demandes en spécifiant un noeud final-/réponses
, ajouté à l'URL de base https://api.stackexchange.com/2.2/- puis obtenez les résultats et affichez-les dans une vue du recycleur. Je vais également vous montrer comment faire cela avec RxJava pour une gestion facile du flux d'état et de données.
Lancez Android Studio et créez un nouveau projet avec une activité vide appelée Activité principale
.
Après avoir créé un nouveau projet, déclarez les dépendances suivantes dans votre build.gradle
. Les dépendances comprennent une vue recycleur, la bibliothèque Retrofit, ainsi que la bibliothèque Gson de Google pour convertir le format JSON en POJO (objets Plain Old Java), ainsi que l'intégration Gson de Retrofit..
// Retrofit compile 'com.squareup.retrofit2: retrofit: 2.1.0' // // Compilation JSON 'com.google.code.gson: gson: 2.6.1' compile 'com.squareup.retrofit2: convertisseur-gson: 2.1 .0 '// recyclerview compile' com.android.support:recyclerview-v7:25.0.1 '
N'oubliez pas de synchroniser le projet pour télécharger ces bibliothèques.
Pour effectuer des opérations sur le réseau, nous devons inclure la L'INTERNET
autorisation dans le manifeste d'application: AndroidManifest.xml.
Nous allons créer nos modèles automatiquement à partir de nos données de réponse JSON en utilisant un outil très utile: jsonschema2pojo..
Copiez et collez https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow dans la barre d'adresse de votre navigateur (ou vous pouvez utiliser Postman si vous connaissez cet outil). Puis appuyez Entrer-cela exécutera une demande GET sur le noeud final donné. Ce que vous verrez en réponse est un tableau d'objets JSON. La capture d'écran ci-dessous est la réponse JSON utilisant Postman..
"items": ["owner": "reputation": 1, "user_id": 6540831, "user_type": "registered", "profile_image": "https://www.gravatar.com/avatar/6a468ce8a8ff42c17923a6009ab77723 ? s = 128 & d = identicon & r = PG & f = 1 "," display_name ":" bobolafrite "," link ":" http://stackoverflow.com/users/6540831/bobolafrite "," is_accepted ": false," score " : 0, "last_activity_date": 1480862271, "creation_date": 1480862271, "answer_id": 40959732, "question_id": 35931342, "owner": "reputation": 629, "user_id": 3054722, "user_type": "registered", "profile_image": "https://www.gravatar.com/avatar/0cf65651ae9a3ba2858ef0d0a7dbf900?s=128&d=identicon&r=PG&f=1", "display_name": "jeremy-denis", "lien": "http : //stackoverflow.com/users/3054722/jeremy-denis "," is_accepted ": false," score ": 0," last_activity_date ": 1480862260," creation_date ": 1480862260," answer_id ": 40959731," question_id " : 40959661,…], "has_more": true, "backoff": 10, "quota_max": 300, "quota_remaining": 241
Copiez cette réponse JSON à partir de votre navigateur ou de Postman.
Maintenant, visitez jsonschema2pojo et collez la réponse JSON dans la zone de saisie..
Sélectionnez un type de source de JSON, style d'annotation de Gson, et décocher Autoriser des propriétés supplémentaires.
Puis cliquez sur le Aperçu bouton pour générer les objets Java.
Vous pourriez vous demander ce que le @SerializedName
et @Exposer
les annotations font dans ce code généré. Ne vous inquiétez pas, je vais tout expliquer!
le @SerializedName
Une annotation est nécessaire pour que Gson mappe les clés JSON avec nos champs. Conformément à la convention de nommage camelCase de Java pour les propriétés de membre de classe, il est déconseillé d'utiliser des traits de soulignement pour séparer les mots d'une variable.. @SerializedName
aide à traduire entre les deux.
@SerializedName ("quota_remaining") @Expose private Integer quotaRemaining;
Dans l'exemple ci-dessus, nous disons à Gson que notre clé JSON quota_remaining
doit être mappé sur le champ Java quotaRemaining
. Si ces deux valeurs étaient identiques, c’est-à-dire si notre clé JSON était quotaRemaining
tout comme le champ Java, il n'y aurait pas besoin de la @SerializedName
annotation sur le terrain car Gson les mapperait automatiquement.
le @Exposer
une annotation indique que ce membre doit être exposé pour la sérialisation ou la désérialisation JSON.
Revenons maintenant à Android Studio. Créez un nouveau sous-paquet dans le paquet principal et nommez-le. Les données. Dans le paquet de données nouvellement créé, créez un autre paquet et nommez-le. modèle. Dans le package de modèle, créez une nouvelle classe Java et nommez-la. Propriétaire
. Maintenant, copiez le Propriétaire
classe qui a été générée par jsonschema2pojo et collée à l'intérieur du Propriétaire
classe que vous avez créée.
importer com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; Classe publique Owner @SerializedName ("reputation") @Expose private Integer reputation; @SerializedName ("user_id") @Expose private Integer userId; @SerializedName ("user_type") @Expose private String userType; @SerializedName ("profile_image") @Expose private String profileImage; @SerializedName ("display_name") @Expose private String displayName; @SerializedName ("link") @Expose private String link; @SerializedName ("accept_rate") @Expose private Integer acceptRate; public Integer getReputation () return réputation; public void setReputation (réputation entière) this.reputation = reputation; public Integer getUserId () return userId; public void setUserId (Integer userId) this.userId = userId; public String getUserType () return userType; public void setUserType (String userType) this.userType = userType; public String getProfileImage () return profileImage; public void setProfileImage (String profileImage) this.profileImage = profileImage; public String getDisplayName () return displayName; public void setDisplayName (String displayName) this.displayName = displayName; public String getLink () return link; public void setLink (lien de chaîne) this.link = link; public Integer getAcceptRate () return acceptRate; public void setAcceptRate (Integer acceptRate) this.acceptRate = acceptRate;
Faire la même chose pour un nouveau Article
classe, copie de jsonschema2pojo.
importer com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; Classe publique Item @SerializedName ("owner") @Expose private Owner owner; @SerializedName ("is_accepted") @Expose private Boolean isAccepted; @SerializedName ("score") @Expose score d'entier privé; @SerializedName ("last_activity_date") @Expose private Integer lastActivityDate; @SerializedName ("creation_date") @Expose private Integer creationDate; @SerializedName ("answer_id") @Expose private Integer answerId; @SerializedName ("question_id") @Expose private Integer questionId; @SerializedName ("last_edit_date") @Expose private Integer lastEditDate; public Owner getOwner () return propriétaire; public void setOwner (Propriétaire) this.owner = propriétaire; public Boolean getIsAccepted () return isAccepted; public void setIsAccepted (booléen est accepté) this.isAccepted = isAccepted; public Integer getScore () return score; public void setScore (score entier) this.score = score; public Integer getLastActivityDate () return lastActivityDate; public void setLastActivityDate (Integer lastActivityDate) this.lastActivityDate = lastActivityDate; public Integer getCreationDate () return creationDate; public void setCreationDate (Integer creationDate) this.creationDate = creationDate; public Integer getAnswerId () return answerId; public void setAnswerId (Integer answerId) this.answerId = answerId; public Integer getQuestionId () return questionId; public void setQuestionId (Integer questionId) this.questionId = questionId; public Integer getLastEditDate () return lastEditDate; public void setLastEditDate (Integer lastEditDate) this.lastEditDate = lastEditDate;
Enfin, créez une classe nomméeSOAnswersResponse
pour les réponses StackOverflow retournées. Vous trouverez le code de cette classe dans jsonschema2pojo en Exemple
. Assurez-vous de mettre à jour le nom de la classe sur SOAnswersResponse
où qu'il se produise.
importer com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; importer java.util.List; Classe publique SOAnswersResponse @SerializedName ("items") @Expose Private List- items = null; @SerializedName ("has_more") @Expose private Boolean hasMore; @SerializedName ("backoff") @Expose private Integer backoff; @SerializedName ("quota_max") @Expose private Integer quotaMax; @SerializedName ("quota_remaining") @Expose private Integer quotaRemaining; liste publique
- getItems () renvoie les éléments; public void setItems (Liste
- items) this.items = items; public Boolean getHasMore () return hasMore; public void setHasMore (Boolean hasMore) this.hasMore = hasMore; public Integer getBackoff () return backoff; public void setBackoff (Integer backoff) this.backoff = backoff; public Integer getQuotaMax () return quotaMax; public void setQuotaMax (Integer quotaMax) this.quotaMax = quotaMax; public Integer getQuotaRemaining () return quotaRemaining; public void setQuotaRemaining (Integer quotaRemaining) this.quotaRemaining = quotaRemaining;
Pour envoyer des requêtes réseau à une API REST avec Retrofit, nous devons créer une instance à l'aide de la Retrofit.Builder
classe et le configurer avec une URL de base.
Créer un nouveau package de sous-package dans le Les données
paquet et nommez-le éloigné
. Maintenant à l'intérieur éloigné
, créer une classe Java et nommez-la RetrofitClient
. Cette classe créera un singleton de Retrofit. Retrofit a besoin d’une URL de base pour construire son instance. Nous allons donc transmettre une URL lors de l’appel. RetrofitClient.getClient (String baseUrl)
. Cette URL sera ensuite utilisée pour construire l'instance à la ligne 13. Nous spécifions également le convertisseur JSON dont nous avons besoin (Gson) à la ligne 14..
import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class RetrofitClient privé statique Retrofit retrofit = null; public public Retrofit getClient (String baseUrl) if (retrofit == null) retrofit = new Retrofit.Builder () .baseUrl (baseUrl) .addConverterFactory (GsonConverterFactory.create ()) .build (); retour ultérieur;
Dans le package distant, créez une interface et appelez-la. SOService
. Cette interface contient des méthodes que nous allons utiliser pour exécuter des requêtes HTTP telles que OBTENIR
, POSTER
, METTRE
, PIÈCE
, et EFFACER
. Pour ce tutoriel, nous allons exécuter une OBTENIR
demande.
importer com.chikeandroid.retrofittutorial.data.model.SOAnswersResponse; importer java.util.List; import retrofit2.Call; import retrofit2.http.GET; interface publique SOService @GET ("/ answers? order = desc & sort = activity & site = stackoverflow") AppelergetAnswers (); @GET ("/ answers? Order = desc & sort = activity & site = stackoverflow") Appeler getAnswers (@Query ("tagged") balises de chaîne);
le @OBTENIR
l'annotation définit explicitement cela OBTENIR
requête qui sera exécutée une fois la méthode appelée. Chaque méthode de cette interface doit avoir une annotation HTTP qui fournit la méthode de requête et l'URL relative. Cinq annotations intégrées sont disponibles: @OBTENIR
, @POSTER
, @METTRE
, @EFFACER
, et @TÊTE
.
Dans la deuxième définition de méthode, nous avons ajouté un paramètre de requête pour filtrer les données du serveur. La rénovation a la @Query ("clé")
annotation à utiliser au lieu de la coder en dur dans le noeud final. La valeur de la clé représente le nom du paramètre dans l'URL. Il sera ajouté à l'URL par Retrofit. Par exemple, si on passe la valeur "Android"
comme argument à la getAnswers (balises de chaîne)
méthode, l'URL complète sera:
https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow&tagged=android
Les paramètres des méthodes d'interface peuvent avoir les annotations suivantes:
@Chemin | substitution de variable pour le point de terminaison de l'API |
@Question | spécifie le nom de la clé de requête avec la valeur du paramètre annoté |
@Corps | charge utile pour l'appel POST |
@Entête | spécifie l'en-tête avec la valeur du paramètre annoté |
Nous allons maintenant créer une classe d’utilité. Nous l'appellerons ApiUtils
. Cette classe aura l’URL de base en tant que variable statique et fournira également le SOService
interface à notre application à travers le getSOService ()
méthode statique.
Classe publique ApiUtils public static final String BASE_URL = "https://api.stackexchange.com/2.2/"; public statique SOService getSOService () return RetrofitClient.getClient (BASE_URL) .create (SOService.class);
Puisque les résultats seront affichés dans une vue du recycleur, nous avons besoin d’un adaptateur. L'extrait de code suivant montre le AnswersAdapter
classe.
Classe publique AnswersAdapter étend RecyclerView.Adapterliste privée - les éléments; contexte privé mContext; private PostItemListener mItemListener; Classe publique ViewHolder étend RecyclerView.ViewHolder implémente View.OnClickListener public TextView titleTv; PostItemListener mItemListener; public ViewHolder (Voir itemView, PostItemListener postItemListener) super (itemView); titleTv = (TextView) itemView.findViewById (android.R.id.text1); this.mItemListener = postItemListener; itemView.setOnClickListener (this); @Override public void onClick (vue View) Item item = getItem (getAdapterPosition ()); this.mItemListener.onPostClick (item.getAnswerId ()); notifyDataSetChanged (); public AnswersAdapter (contexte de contexte, liste
- posts, PostItemListener itemListener) mItems = posts; mContext = context; mItemListener = itemListener; @Override public AnswersAdapter.ViewHolder onCreateViewHolder (parent de ViewGroup, int viewType) Contexte de contexte = parent.getContext (); LayoutInflater inflater = LayoutInflater.from (contexte); Voir postView = inflater.inflate (android.R.layout.simple_list_item_1, parent, false); ViewHolder viewHolder = new ViewHolder (postView, this.mItemListener); retourne viewHolder; @Override public void onBindViewHolder (titulaire de AnswersAdapter.ViewHolder, position int) Item item = mItems.get (position); TextView textView = holder.titleTv; textView.setText (item.getOwner (). getDisplayName ()); @Override public int getItemCount () return mItems.size (); public void updateAnswers (Liste
- items) mItems = items; notifyDataSetChanged (); élément privé getItem (int adapterPosition) return mItems.get (adapterPosition); interface publique PostItemListener void onPostClick (id long);
À l'intérieur de onCreate ()
méthode du Activité principale
, nous initialisons une instance du SOService
interface (ligne 9), la vue recycleur, ainsi que l'adaptateur. Enfin, nous appelons le loadAnswers ()
méthode.
private AnswersAdapter mAdapter; RecyclerView privé mRecyclerView; SOService privé mService; @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); mService = ApiUtils.getSOService (); mRecyclerView = (RecyclerView) findViewById (R.id.rv_answers); mAdapter = new AnswersAdapter (this, nouvel ArrayList- (0), new AnswersAdapter.PostItemListener () @Override public void onPostClick (id long) Toast.makeText (MainActivity.this, "ID post est" + id, Toast.LENGTH_SHORT) .show (); ); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager (this); mRecyclerView.setLayoutManager (layoutManager); mRecyclerView.setAdapter (mAdapter); mRecyclerView.setHasFixedSize (true); RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration (this, DividerItemDecoration.VERTICAL_LIST); mRecyclerView.addItemDecoration (itemDecoration); loadAnswers ();
le loadAnswers ()
méthode effectue une requête réseau en appelant enqueue ()
. Lorsque la réponse est renvoyée, Retrofit nous aide à analyser la réponse JSON dans une liste d'objets Java. (Ceci est rendu possible en utilisant GsonConverter
.)
public void loadAnswers () mService.getAnswers (). en file d'attente (nouveau rappel() @Override public void onResponse (Call appel, réponse réponse) if (response.isSuccessful ()) mAdapter.updateAnswers (response.body (). getItems ()); Log.d ("MainActivity", "publications chargées à partir de l'API"); else int statusCode = response.code (); // traite les erreurs de requête en fonction du code d'état @Override public void onFailure (Call appel, Throwable t) showErrorMessage (); Log.d ("MainActivity", "erreur lors du chargement à partir de l'API"); );
enqueue ()
enqueue ()
envoie la demande de manière asynchrone et informe votre application par un rappel lorsque la réponse est renvoyée. Cette demande étant asynchrone, Retrofit la gère sur un thread d'arrière-plan afin que le thread d'interface utilisateur principal ne soit ni bloqué ni perturbé..
Utiliser enqueue ()
, vous devez implémenter deux méthodes de rappel:
onResponse ()
onFailure ()
Une seule de ces méthodes sera appelée en réponse à une requête donnée.
onResponse ()
: appelé pour une réponse HTTP reçue. Cette méthode est appelée pour une réponse qui peut être traitée correctement même si le serveur renvoie un message d'erreur. Donc, si vous obtenez un code d'état de 404 ou 500, cette méthode sera toujours appelée. Pour obtenir le code de statut afin de pouvoir gérer des situations basées sur celles-ci, vous pouvez utiliser la méthode Code de réponse()
. Vous pouvez également utiliser le est réussi()
méthode permettant de savoir si le code d'état est compris entre 200 et 300, indiquant le succès.onFailure ()
: invoqué lorsqu'une exception réseau s'est produite lors de la communication avec le serveur ou lorsqu'une exception inattendue s'est produite lors du traitement de la demande ou du traitement de la réponse. Pour effectuer une requête synchrone, vous pouvez utiliser le exécuter()
méthode. Sachez que les méthodes synchrones sur le thread principal / d'interface utilisateur bloquent toute action de l'utilisateur. Donc, n'exécutez pas de méthodes synchrones sur le thread principal / interface utilisateur d'Android! Au lieu de cela, exécutez-les sur un thread d'arrière-plan.
Vous pouvez maintenant lancer l'application.
Si vous êtes un fan de RxJava, vous pouvez facilement implémenter Retrofit avec RxJava. Dans Retrofit 1, il était intégré par défaut, mais dans Retrofit 2, vous devez inclure des dépendances supplémentaires. Retrofit est livré avec un adaptateur par défaut pour l'exécution Appel
les instances. Vous pouvez donc modifier le mécanisme d’exécution de Retrofit pour inclure RxJava en incluant le fichier RxJava. CallAdapter
.
Ajouter les dépendances.
compiler 'io.reactivex: rxjava: 1.1.6' compiler 'io.reactivex: rxandroid: 1.2.1' compiler 'com.squareup.retrofit2: adapter-rxjava: 2.1.0'
Ajouter le nouvel CallAdapter RxJavaCallAdapterFactory.create ()
lors de la création d'une instance de modification.
public statique Retrofit getClient (String baseUrl) if (retrofit == null) retrofit = new Retrofit.Builder () .baseUrl (baseUrl) .addCallAdapterFactory (RxJavaCallAdapterFactory.create ()) .addConverterFactory (GsonConverterFactory (GsonConverterFactory). (); retour ultérieur;
Maintenant, mettez à jour le getAnswers ()
méthodes pour retourner Observable
s:
@GET ("/ answers? Order = desc & sort = activity & site = stackoverflow") ObservablegetAnswers (); @GET ("/ answers? Order = desc & sort = activity & site = stackoverflow") Observable getAnswers (@Query ("tagged") balises String);
Lors de la demande, notre abonné anonyme répond au flux de l'observable qui émet des événements, dans notre cas SOAnswersResponse
. le onNext
La méthode est ensuite appelée lorsque notre abonné reçoit tout événement émis qui est ensuite transmis à notre adaptateur..
@Override public void loadAnswers () mService.getAnswers (). SubscribeOn (Schedulers.io ()). ObserveOn (AndroidSchedulers.mainThread ()) .subscribe (nouvel abonné() @Override public nul onCompleted () @Override public vide onError (Throwable e) @Override public nul onNext (SOAnswersResponse soAnswersResponse) mAdapter.updateAnswers (soAnswersResponse.getItems ()); );
Découvrez Premiers pas avec ReactiveX sur Android par Ashraff Hathibelagal pour en savoir plus sur RxJava et RxAndroid..
Dans ce didacticiel, vous avez découvert Retrofit: pourquoi et comment l’utiliser. J'ai aussi expliqué comment ajouter l'intégration de RxJava à Retrofit. Dans mon prochain post, je vais vous montrer comment jouer POSTER
, METTRE
, et EFFACER
, comment envoyer Form-Urlencoded
données, et comment annuler les demandes.
Pour en savoir plus sur Retrofit, reportez-vous à la documentation officielle. Et en attendant, découvrez certains de nos autres cours et tutoriels sur le développement d'applications Android..