Inizia con Retrofit 2 Client HTTP

Cosa starai creando

Che cosa è il retrofit?

Retrofit è un client HTTP sicuro per tipo per Android e Java. Retrofit semplifica la connessione a un servizio Web REST traducendo l'API in interfacce Java. In questo tutorial, ti mostrerò come utilizzare una delle librerie HTTP più popolari e spesso raccomandate disponibili per Android. 

Questa potente libreria semplifica il consumo di dati JSON o XML che vengono poi analizzati in Plain Old Java Objects (POJO). OTTENEREINVIAREMETTEREPATCH, e ELIMINA le richieste possono essere tutte eseguite. 

Come la maggior parte dei software open source, Retrofit è stato costruito su altre potenti librerie e strumenti. Dietro le quinte, Retrofit utilizza OkHttp (dello stesso sviluppatore) per gestire le richieste di rete. Inoltre, Retrofit non ha un convertitore JSON integrato per l'analisi da oggetti JSON a Java. Porta invece il supporto per le seguenti librerie di convertitori JSON per gestire ciò: 

  • GSON: com.squareup.retrofit: convertitore-GSON
  • Jackson: com.squareup.retrofit: convertitore-jackson
  • Moshi: com.squareup.retrofit: convertitore-moshi

Per i buffer di protocollo, i supporti di retrofit:

  • Protobuf: com.squareup.retrofit2: convertitore-protobuf
  • Filo: com.squareup.retrofit2: convertitore fili

E per XML, Retrofit supporta:

  • Quadro semplice: com.squareup.retrofit2: convertitore-simpleframework

Quindi, perché utilizzare Retrofit?

Sviluppare la propria libreria HTTP sicura per l'interfaccia con un'API REST può essere un vero problema: è necessario gestire molte funzionalità come effettuare connessioni, memorizzazione nella cache, riprovare richieste non riuscite, threading, analisi delle risposte, gestione degli errori e altro. Il retrofit, d'altra parte, è molto ben pianificato, documentato e testato, una libreria testata in battaglia che ti farà risparmiare un sacco di tempo prezioso e mal di testa.

In questo tutorial, spiegherò come utilizzare Retrofit 2 per gestire le richieste di rete creando una semplice app per interrogare risposte recenti dall'API di Stack Exchange. Ci esibiremo OTTENERE richieste specificando un endpoint-/ risposte, aggiunto all'URL di base https://api.stackexchange.com/2.2/- ottenere i risultati e visualizzarli in una visualizzazione di riciclaggio. Ti mostrerò anche come farlo con RxJava per una facile gestione del flusso di stato e dei dati.

1. Creare un progetto per Android Studio

Avvia Android Studio e crea un nuovo progetto con un'attività vuota chiamata Attività principale.

2. Dichiarare le dipendenze

Dopo aver creato un nuovo progetto, dichiara le seguenti dipendenze nel tuo build.gradleLe dipendenze includono una vista riciclatore, la libreria Retrofit e anche la libreria Gson di Google per convertire JSON in POJO (Plain Old Java Objects) e l'integrazione di Gof Retrofit. 

// Retrofit compile 'com.squareup.retrofit2: retrofit: 2.1.0' // JSON Parsing compile 'com.google.code.gson: gson: 2.6.1' compile 'com.squareup.retrofit2: convertitore-gson: 2.1 .0 '// recyclerview compile' com.android.support:recyclerview-v7:25.0.1 ' 

Non dimenticare di sincronizzare il progetto per scaricare queste librerie. 

3. Aggiunta dell'autorizzazione Internet

Per eseguire operazioni di rete, è necessario includere il INTERNETpermesso nel manifest dell'applicazione: AndroidManifest.xml.

           

4. Generazione automatica di modelli

Creeremo automaticamente i nostri modelli dai nostri dati di risposta JSON sfruttando uno strumento molto utile: jsonschema2pojo. 

Ottieni i dati JSON di esempio

Copia e incolla https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow nella barra degli indirizzi del tuo browser (oppure potresti usare Postman se conosci questo strumento). Quindi premere accedere-questo eseguirà una richiesta GET sull'endpoint specificato. Quello che vedrai in risposta è un array di oggetti JSON. Lo screenshot seguente è la risposta JSON che utilizza 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," punteggio " : 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", "link": "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

Copia questa risposta JSON dal tuo browser o Postman. 

Mappare i dati JSON su Java

Ora visita jsonschema2pojo e incolla la risposta JSON nella casella di input.

Seleziona un tipo di fonte di JSON, stile di annotazione di GSON, e deselezionare Consenti proprietà aggiuntive

Quindi fare clic su Anteprima pulsante per generare gli oggetti Java. 

Potresti chiederti che cosa @SerializedName e @Esporre le annotazioni fanno in questo codice generato. Non preoccuparti, ti spiegherò tutto!

Il @SerializedName l'annotazione è necessaria per Gson per mappare le chiavi JSON con i nostri campi. In linea con la convenzione di denominazione CamelCase di Java per le proprietà dei membri della classe, non è consigliabile utilizzare caratteri di sottolineatura per separare le parole in una variabile. @SerializedName aiuta a tradurre tra i due.

@SerializedName ("quota_remaining") @Expose private Integer quotaRemaining;

Nell'esempio sopra, stiamo dicendo a Gson che la nostra chiave JSON quota_remaining dovrebbe essere mappato al campo Java quotaRemaining.  Se entrambi questi valori erano uguali, cioè se la nostra chiave JSON era quotaRemaining proprio come il campo Java, quindi non ci sarebbe bisogno di @SerializedName annotazione sul campo perché Gson li mapperebbe automaticamente.

Il @Esporre l'annotazione indica che questo membro deve essere esposto per la serializzazione o deserializzazione JSON. 

Importa modelli di dati su Android Studio

Ora torniamo ad Android Studio. Crea un nuovo sotto-pacchetto all'interno del pacchetto principale e nominalo dati. All'interno del pacchetto dati appena creato, crea un altro pacchetto e chiamalo modello. All'interno del pacchetto del modello, creare una nuova classe Java e denominarla Proprietario. Ora copia il Proprietario classe che è stata generata da jsonschema2pojo e incollarla all'interno di Proprietario classe che hai creato. 

import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; Proprietario di classe pubblica @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 reputation;  public void setReputation (Integer reputation) 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 (String link) this.link = link;  public Integer getAcceptRate () return acceptRate;  public void setAcceptRate (Integer acceptRate) this.acceptRate = acceptRate; 

Fai la stessa cosa per un nuovo Articolo classe, copiata da jsonschema2pojo. 

import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; Articolo di classe pubblica @SerializedName ("owner") @Expose private Owner owner; @SerializedName ("is_accepted") @Expose Boolean privato isAccepted; @SerializedName ("score") @Expose private Integer score; @SerializedName ("last_activity_date") @Expose Integer privato lastActivityDate; @SerializedName ("creation_date") @Expose Private Integer creationDate; @SerializedName ("answer_id") @Expose Private Integer answerId; @SerializedName ("question_id") @Expose Intero privato questionId; @SerializedName ("last_edit_date") @Expose Intero privato lastEditDate; proprietario pubblico getOwner () return owner;  public void setOwner (proprietario proprietario) this.owner = owner;  public Boolean getIsAccepted () return isAccepted;  public void setIsAccepted (Boolean isAccepted) this.isAccepted = isAccepted;  public Integer getScore () return score;  public void setScore (Integer score) 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 Intero getAnswerId () return ID di risposta;  public void setAnswerId (Integer answerId) this.answerId = answerId;  public Integer getQuestionId () return QuestionId;  public void setQuestionId (Interiger questionId) this.questionId = questionId;  public Integer getLastEditDate () return lastEditDate;  public void setLastEditDate (Integer lastEditDate) this.lastEditDate = lastEditDate; 

Infine, crea una classe chiamataSOAnswersResponse per le risposte StackOverflow restituite. Troverai il codice per questa classe in jsonschema2pojo come Esempio. Assicurati di aggiornare il nome della classe su SOAnswersResponse ovunque si verifichi. 

import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; import java.util.List; public class SOAnswersResponse @SerializedName ("items") @Expose private List items = null; @SerializedName ("has_more") @Expose Boolean privato hasMore; @SerializedName ("backoff") @Expose backoff Intero privato; @SerializedName ("quota_max") @Expose intero Numero intero quotaMax; @SerializedName ("quota_remaining") @Expose private Integer quotaRemaining; lista pubblica getItems () return items;  setItems vuoto pubblico (Elenco articoli) this.items = articoli;  public Boolean getHasMore () return hasMore;  public void setHasMore (Boolean hasMore) this.hasMore = hasMore;  public Intero getBackoff () return backoff;  public void setBackoff (Integer backoff) this.backoff = backoff;  public Intero getQuotaMax () return quotaMax;  public void setQuotaMax (Integer quotaMax) this.quotaMax = quotaMax;  public Intero getQuotaRemaining () return quotaRemaining;  public void setQuotaRemaining (Integer quotaRemaining) this.quotaRemaining = quotaRemaining; 

5. Creazione dell'istanza di aggiornamento

Per inviare richieste di rete a un'API REST con Retrofit, dobbiamo creare un'istanza usando il Retrofit.Builder classe e configurarlo con un URL di base. 

Crea un nuovo pacchetto sub-pacchetto all'interno del dati pacchetto e chiamarlo a distanza. Ora dentro a distanza, creare una classe Java e nominarla RetrofitClient. Questa classe creerà un singleton di Retrofit. Il retrofit richiede un URL di base per creare la sua istanza, quindi passeremo un URL quando chiameremo RetrofitClient.getClient (String baseUrl). Questo URL verrà quindi utilizzato per creare l'istanza nella riga 13. Stiamo anche specificando il convertitore JSON di cui abbiamo bisogno (Gson) nella riga 14. 

importazione retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class RetrofitClient retrofit statico privato retrofit = null; public static Retrofit getClient (String baseUrl) if (retrofit == null) retrofit = new Retrofit.Builder () .baseUrl (baseUrl) .addConverterFactory (GsonConverterFactory.create ()) .build ();  retrofit di ritorno;  

6. Creazione dell'interfaccia API

All'interno del pacchetto remoto, crea un'interfaccia e chiamala SOService. Questa interfaccia contiene metodi che utilizzeremo per eseguire richieste HTTP come OTTENEREINVIAREMETTERE, PATCH, e ELIMINA. Per questo tutorial, stiamo per eseguire a OTTENERE richiesta. 

import com.chikeandroid.retrofittutorial.data.model.SOAnswersResponse; import java.util.List; import retrofit2.Call; import retrofit2.http.GET; interfaccia pubblica SOService @GET ("/ risposte? order = desc & sort = activity & site = stackoverflow") Chiama getAnswers (); @GET ("/ risponde? Order = desc & sort = activity & site = stackoverflow") Chiama getAnswers (@Query ("tagged") Tag delle stringhe);  

Il @OTTENERE l'annotazione lo definisce esplicitamente OTTENERE richiesta che verrà eseguita una volta chiamato il metodo. Ogni metodo in questa interfaccia deve avere un'annotazione HTTP che fornisce il metodo di richiesta e l'URL relativo. Sono disponibili cinque annotazioni integrate: @OTTENERE@INVIARE, @METTERE@ELIMINA, e @CAPO.

Nella seconda definizione del metodo, abbiamo aggiunto un parametro di query per filtrare i dati dal server. Il retrofit ha il @ Query ( "chiave") annotazione da utilizzare invece di codificarla nel punto finale. Il valore della chiave rappresenta il nome del parametro nell'URL. Sarà aggiunto all'URL di Retrofit. Ad esempio, se passiamo il valore "Android" come argomento per il getAnswers (tag delle stringhe) metodo, l'URL completo sarà:

https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow&tagged=android

I parametri dei metodi di interfaccia possono avere le seguenti annotazioni:

@Sentiero sostituzione variabile per l'endpoint API
@query specifica il nome della chiave della query con il valore del parametro annotato
@Corpo carico utile per la chiamata POST 
@Intestazione specifica l'intestazione con il valore del parametro annotato

7. Creazione degli API Utils

Ora creeremo una classe di utilità. Lo nomineremo ApiUtils. Questa classe avrà l'URL di base come variabile statica e fornirà anche il SOService interfaccia alla nostra applicazione attraverso il getSOService () metodo statico.

public class ApiUtils public static final String BASE_URL = "https://api.stackexchange.com/2.2/"; public static SOService getSOService () return RetrofitClient.getClient (BASE_URL) .create (SOService.class);  

8. Visualizza su RecyclerView

Poiché i risultati verranno visualizzati in una visualizzazione di riciclaggio, abbiamo bisogno di un adattatore. Il seguente frammento di codice mostra il AnswersAdapter classe.

classe pubblica AnswersAdapter estende RecyclerView.Adapter Lista privata mItems; contesto privato mContext; PostItemListener privato mItemListener; public class ViewHolder estende RecyclerView.ViewHolder implementa View.OnClickListener public TextView titleTv; PostItemListener mItemListener; public ViewHolder (Visualizza itemView, PostItemListener postItemListener) super (itemView); titleTv = (TextView) itemView.findViewById (android.R.id.text1); this.mItemListener = postItemListener; itemView.setOnClickListener (questo);  @Override public void onClick (Visualizza vista) Item item = getItem (getAdapterPosition ()); this.mItemListener.onPostClick (item.getAnswerId ()); notifyDataSetChanged ();  public AnswersAdapter (Contesto contesto, Elenco post, PostItemListener itemListener) mItems = posts; mContext = contesto; mItemListener = itemListener;  @Override public AnswersAdapter.ViewHolder onCreateViewHolder (ViewGroup parent, int viewType) Context context = parent.getContext (); LayoutInflater inflater = LayoutInflater.from (context); Visualizza postView = inflater.inflate (android.R.layout.simple_list_item_1, parent, false); ViewHolder viewHolder = new ViewHolder (postView, this.mItemListener); return viewHolder;  @Override public void onBindViewHolder (AnswersAdapter.ViewHolder holder, int position) Item item = mItems.get (position); TextView textView = holder.titleTv; textView.setText (item.getOwner () getDisplayName ().);  @Override public int getItemCount () return mItems.size ();  public void updateAnswers (Lista items) mItems = items; notifyDataSetChanged ();  private Item getItem (int adapterPosition) return mItems.get (adapterPosition);  interfaccia pubblica PostItemListener void onPostClick (long id); 

9. Esecuzione della richiesta

Dentro il onCreate () metodo del Attività principale, inizializziamo un'istanza di SOService interfaccia (riga 9), la vista del riciclatore e anche l'adattatore. Infine, chiamiamo il loadAnswers () metodo. 

 private AnswersAdapter mAdapter; private RecyclerView mRecyclerView; SOService mService privato; @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 (questo, nuovo ArrayList(0), new AnswersAdapter.PostItemListener () @Override public void onPostClick (long id) Toast.makeText (MainActivity.this, "ID post è" + 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 (); 

Il loadAnswers () metodo effettua una richiesta di rete chiamando enqueue (). Quando la risposta ritorna, Retrofit ci aiuta ad analizzare la risposta JSON a un elenco di oggetti Java. (Ciò è reso possibile dall'uso GsonConverter.)  

public void loadAnswers () mService.getAnswers (). enqueue (new Callback() @ Override public void onResponse (Call chiamata, risposta risposta) if (response.isSuccessful ()) mAdapter.updateAnswers (response.body (). getItems ()); Log.d ("MainActivity", "posts loaded from API");  else int statusCode = response.code (); // gestisce gli errori di richiesta in base al codice di stato @Override public void onFailure (Call call, Throwable t) showErrorMessage (); Log.d ("MainActivity", "errore di caricamento da API"); ); 

10. Comprensione enqueue ()

enqueue () invia in modo asincrono la richiesta e avvisa la tua app con un callback quando ritorna una risposta. Poiché questa richiesta è asincrona, Retrofit la gestisce su un thread in background in modo che il thread dell'interfaccia utente principale non sia bloccato o interferito con.

Usare enqueue (), devi implementare due metodi di callback:

  • onResponse ()
  • onFailure ()

Solo uno di questi metodi verrà chiamato in risposta a una determinata richiesta. 

  • onResponse (): invocato per una risposta HTTP ricevuta. Questo metodo viene chiamato per una risposta che può essere gestita correttamente anche se il server restituisce un messaggio di errore. Quindi se ottieni un codice di stato 404 o 500, questo metodo verrà comunque chiamato. Per ottenere il codice di stato al fine di gestire le situazioni basate su di essi, è possibile utilizzare il metodo Codice di risposta(). Puoi anche usare il isSuccessful () metodo per scoprire se il codice di stato è nell'intervallo 200-300, indicando il successo.
  • onFailure (): richiamato quando si è verificata un'eccezione di rete che comunica al server o quando si è verificata un'eccezione imprevista durante la gestione della richiesta o l'elaborazione della risposta. 

Per eseguire una richiesta sincrona, è possibile utilizzare il eseguire() metodo. Tieni presente che i metodi sincroni sul thread principale / dell'interfaccia utente bloccheranno qualsiasi azione dell'utente. Quindi non eseguire metodi sincroni sul thread principale / dell'interfaccia utente di Android! Invece, eseguili su un thread in background.

11. Testare l'app

Ora puoi eseguire l'app. 

12. Integrazione RxJava

Se sei un fan di RxJava, puoi facilmente implementare Retrofit con RxJava. In Retrofit 1 è stato integrato per impostazione predefinita, ma in Retrofit 2 è necessario includere alcune dipendenze aggiuntive. Il retrofit viene fornito con un adattatore predefinito per l'esecuzione Chiamata le istanze. Quindi è possibile modificare il meccanismo di esecuzione di Retrofit per includere RxJava includendo RxJava CallAdapter

Passo 1

Aggiungi le dipendenze.

compile 'io.reactivex: rxjava: 1.1.6' compila 'io.reactivex: rxandroid: 1.2.1' compile 'com.squareup.retrofit2: adapter-rxjava: 2.1.0'

Passo 2

Aggiungi il nuovo CallAdapter RxJavaCallAdapterFactory.create () quando si costruisce un'istanza di Retrofit.  

public static Retrofit getClient (String baseUrl) if (retrofit == null) retrofit = new Retrofit.Builder () .baseUrl (baseUrl) .addCallAdapterFactory (RxJavaCallAdapterFactory.create ()) .addConverterFactory (GsonConverterFactory.create ()) .build ();  retrofit di ritorno; 

Passaggio 3

Ora aggiorna il getAnswers ()  metodi per tornare OsservabileS:

@GET ("/ risponde? Order = desc & sort = activity & site = stackoverflow") Osservabile getAnswers (); @GET ("/ risponde? Order = desc & sort = activity & site = stackoverflow") Osservabile getAnswers (@Query ("tagged") Tag delle stringhe); 

Passaggio 4

Quando facciamo le richieste, il nostro abbonato anonimo risponde allo stream osservabile che emette eventi, nel nostro caso SOAnswersResponse. Il onNext il metodo viene quindi chiamato quando il nostro abbonato riceve qualsiasi evento emesso che viene poi passato al nostro adattatore. 

@Override public void loadAnswers () mService.getAnswers (). SubscribeOn (Schedulers.io ()). ObservOn (AndroidSchedulers.mainThread ()) .subscribe (new Subscriber() @Override public void onCompleted ()  @Override public void onError (Throwable e)  @Override public void onNext (SOAnswersResponse soAnswersResponse) mAdapter.updateAnswers (soAnswersResponse.getItems ()); ); 

Scopri come iniziare con ReactiveX su Android di Ashraff Hathibelagal per saperne di più su RxJava e RxAndroid. 

Conclusione

In questo tutorial, hai imparato a conoscere Retrofit: perché dovresti usarlo e come. Ho anche spiegato come aggiungere l'integrazione RxJava con Retrofit. Nel mio prossimo post, ti mostrerò come esibirti INVIAREMETTERE, e ELIMINA, come spedire Form-urlencoded dati e come cancellare le richieste. 

Per ulteriori informazioni su Retrofit, fare riferimento alla documentazione ufficiale. E nel frattempo, dai uno sguardo ad alcuni dei nostri altri corsi e tutorial sullo sviluppo di app per Android.

  • Comunicazione all'interno di un'app Android con EventBus

    Greenrobot EventBus è una popolare libreria open source che utilizza il modello publish / subscribe per la comunicazione tra i componenti del sistema Android. Nel…
    Chike Mgbemena
    androide
  • Concorrenza pratica su Android con HaMeR

    In questo tutorial esploreremo il framework HaMeR (Handler, Message and Runnable), uno dei più potenti modelli di concorrenza disponibili su Android. Con un…
    Tin Megali
    SDK Android
  • Android From Scratch: utilizzo delle API REST

    In questo tutorial, ti mostrerò come utilizzare le classi e i metodi disponibili nell'SDK di Android per connettersi a server Web remoti e interagire con ...
    Ashraff Hathibelagal
    SDK Android
  • Inizia con un modello di app Android in 60 secondi

    CodeCanyon ha centinaia di modelli di app per Android che puoi utilizzare per iniziare il tuo sviluppo. Questo video ti mostrerà come installare e personalizzare un ...
    Ashraff Hathibelagal
    SDK Android