Introduktion til eftermontering

1. Oversigt

Retrofit er en typesikker HTTP-klient til Android og Java - udviklet af Square (Dagger, Okhttp).

I denne artikel vil vi forklare, hvordan du bruger eftermontering med fokus på dets mest interessante funktioner. Mere især vil vi diskutere den synkrone og asynkrone API, hvordan man bruger den med godkendelse, logning og nogle gode modelleringspraksis.

2. Opsætning af eksemplet

Vi starter med at tilføje Retrofit-biblioteket og Gson-konverteren:

 com.squareup.retrofit2 eftermontering 2.3.0 com.squareup.retrofit2 konverter-gson 2.3.0 

For de nyeste versioner, se Retrofit og converter-gson på Maven Central repository.

3. API-modellering

Eftermonter modeller REST-slutpunkter som Java-grænseflader, hvilket gør dem meget enkle at forstå og forbruge.

Vi modellerer bruger-API'en fra GitHub; dette har en slutpunkt, der returnerer dette i JSON-format:

{login: "mojombo", id: 1, url: "//api.github.com/users/mojombo", ...}

Eftermontering fungerer ved at modellere over en basis URL og ved at gøre grænseflader returnere enhederne fra REST-slutpunktet.

For enkelheds skyld vil vi tage en lille del af JSON ved at modellere vores Bruger klasse, der skal tage værdierne, når vi har modtaget dem:

offentlig klasse Bruger {privat String login; privat lang id; privat String url; // ... // standard getters an setters}

Vi kan se, at vi kun tager et undersæt af egenskaber til dette eksempel. Eftermontering klager ikke over manglende egenskaber - da det kun kortlægger det, vi har brug for, klager det ikke engang, hvis vi tilføjede egenskaber, der ikke er i JSON.

Nu kan vi gå til grænseflademodelleringen og forklare nogle af retrofit-kommentarerne:

offentlig grænseflade UserService {@GET ("/ brugere") offentlig opkald getUsers (@Query ("per_page") int per_page, @Query ("page") int side); @GET ("/ brugere / {brugernavn}") offentlig Opkald getUser (@Path ("brugernavn") String brugernavn); }

Metadataene, der leveres med annoteringer, er nok til, at værktøjet kan generere arbejdsimplementeringer.

Det @FÅ annotation fortæller klienten, hvilken HTTP-metode, der skal bruges, og på hvilken ressource, f.eks. ved at angive en basis-URL på “//api.github.com”, vil den sende anmodningen til “//api.github.com/users” .

Den førende “/” på vores relative URL fortæller Retrofit, at det er en absolut sti på værten.

En anden ting at bemærke er, at vi bruger helt valgfri @Forespørgsel parametre, som kan sendes som nul, hvis vi ikke har brug for dem, vil værktøjet sørge for at ignorere disse parametre, hvis de ikke har værdier.

Og sidst men ikke mindst, @Sti lad os specificere en styparameter, der placeres i stedet for den markering, vi brugte i stien.

4. Synkron / asynkron API

For at konstruere et HTTP-anmodningskald skal vi først oprette vores eftermonteringsobjekt:

OkHttpClient.Builder httpClient = ny OkHttpClient.Builder (); Eftermontering eftermontering = ny Retrofit.Builder () .baseUrl ("// api.github.com/") .addConverterFactory (GsonConverterFactory.create ()) .client (httpClient.build ()) .build ();

Eftermontering giver en praktisk bygherre til konstruktion af vores krævede objekt. Det har brug for den basale URL, der skal bruges til hvert servicekald og en konverterfabrik - som tager sig af parsing af data, vi sender, og også de svar, vi får.

I dette eksempel skal vi bruge GsonConverterFactory, som skal kortlægge vores JSON-data til Bruger klasse, vi definerede tidligere.

Det er vigtigt at bemærke, at forskellige fabrikker tjener forskellige formål, så husk at vi også kan bruge fabrikker til XML, proto-buffere eller endda oprette en til en brugerdefineret protokol. For en liste over allerede implementerede fabrikker kan vi se her.

Den sidste afhængighed er OKHttpClient - som er en HTTP & HTTP / 2-klient til Android- og Java-applikationer. Dette tager sig af forbindelsen til serveren og afsendelse og hentning af information. Vi kunne også tilføje headere og interceptors til hvert opkald, som vi vil se i vores godkendelsessektion.

Nu hvor vi har vores eftermonteringsobjekt, kan vi konstruere vores servicekald, lad os se på, hvordan man gør dette på den synkrone måde:

UserService service = retrofit.create (UserService.class); Ring til callSync = service.getUser ("eugenp"); prøv {Response response = callSync.execute (); Brugerbruger = respons.body (); } fangst (undtagelse ex) {...}

Her kan vi se, hvordan Retrofit tager sig af opbygningen af ​​vores servicegrænseflade ved at indsprøjte den kode, der er nødvendig for at fremsætte anmodningen, baseret på vores tidligere kommentarer.

Derefter får vi en Opkald objekt, der er det, der bruges til at udføre anmodningen til GitHub API. Den vigtigste metode her er udføre, som bruges til at udføre et opkald synkront og vil blokere den aktuelle tråd, mens data overføres.

Når opkaldet er udført med succes, kan vi hente svarets krop - allerede på et brugerobjekt - takket være vores GsonConverterFactory.

At foretage et synkront opkald er meget let, men normalt bruger vi en ikke-blokerende asynkron anmodning:

UserService service = retrofit.create (UserService.class); Ring til callAsync = service.getUser ("eugenp"); callAsync.enqueue (ny tilbagekaldelse () {@Override public void onResponse (Call call, Response response) {User user = response.body ();} @ Override public void onFailure (Call call, Throwable throwable) {System.out.println) (kastbar);}});

Nu i stedet for udførelsesmetoden bruger vi enqueue metode - som tager en Ring tilbageinterface som en parameter til at håndtere anmodningens succes eller fiasko. Bemærk, at dette udføres i en separat tråd.

Når opkaldet er afsluttet med succes, kan vi hente kroppen på samme måde som vi gjorde tidligere.

5. Gør en genanvendelig ServiceGenerator Klasse

Nu hvor vi så, hvordan vi konstruerer vores Retrofit-objekt, og hvordan vi bruger en API, kan vi se, at vi ikke vil fortsætte med at skrive bygherren igen og igen.

Hvad vi ønsker er en genanvendelig klasse, der giver os mulighed for at oprette dette objekt en gang og genbruge det i hele vores applikations levetid:

offentlig klasse GitHubServiceGenerator {privat statisk endelig streng BASE_URL = "//api.github.com/"; privat statisk Retrofit.Builder builder = ny Retrofit.Builder () .baseUrl (BASE_URL) .addConverterFactory (GsonConverterFactory.create ()); privat statisk eftermontering eftermontering = builder.build (); privat statisk OkHttpClient.Builder httpClient = ny OkHttpClient.Builder (); offentlig statisk S createService (Class serviceClass) {return retrofit.create (serviceClass); }}

Al logikken med at oprette Retrofit-objektet flyttes nu til dette GitHubServiceGenerator klasse, dette gør det til en bæredygtig klientklasse, der forhindrer, at koden gentages.

Her er et simpelt eksempel på, hvordan du bruger det:

UserService service = GitHubServiceGenerator.createService (UserService.class);

Nu hvis vi f.eks. Skulle skabe et RepositoryService, vi kunne genbruge denne klasse og forenkle skabelsen.

I det næste afsnit, vi udvider det og tilføjer godkendelsesfunktioner.

6. Godkendelse

De fleste API'er har en vis godkendelse for at sikre adgang til det.

Under hensyntagen til vores tidligere generatorklasse vil vi tilføje en opret servicemetode, der tager et JWT-token med Bemyndigelse header :

offentlig statisk S createService (Class serviceClass, final String token) {if (token! = null) {httpClient.interceptors (). clear (); httpClient.addInterceptor (chain -> {Request original = chain.request (); Request request = original.newBuilder () .header ("Authorization", token) .build (); return chain.proceed (request);}); builder.client (httpClient.build ()); eftermontering = builder.build (); } returner retrofit.create (serviceClass); }

For at tilføje en header til vores anmodning skal vi bruge interceptor-funktionerne i OkHttp; vi gør dette ved at bruge vores tidligere definerede builder og ved at rekonstruere Retrofit-objektet.

Bemærk, at dette er et simpelt godkendelseseksempel, men ved brug af interceptors kan vi bruge enhver godkendelse som OAuth, bruger / adgangskode osv.

7. Logning

I dette afsnit vil vi udvide vores yderligere GitHubServiceGenerator til logfunktioner, som er meget vigtige til fejlfindingsformål i hvert projekt.

Vi skal bruge vores tidligere viden om interceptors, men vi har brug for en yderligere afhængighed, som er HttpLoggingInterceptor fra OkHttp, lad os tilføje det til vores pom.xml:

 com.squareup.okhttp3 logging-interceptor 3.9.0 

Lad os nu udvide vores GitHubServiceGenerator klasse:

offentlig klasse GitHubServiceGenerator {privat statisk endelig streng BASE_URL = "//api.github.com/"; privat statisk Retrofit.Builder builder = ny Retrofit.Builder () .baseUrl (BASE_URL) .addConverterFactory (GsonConverterFactory.create ()); privat statisk eftermontering eftermontering = builder.build (); privat statisk OkHttpClient.Builder httpClient = ny OkHttpClient.Builder (); privat statisk HttpLoggingInterceptor logging = ny HttpLoggingInterceptor () .setLevel (HttpLoggingInterceptor.Level.BASIC); offentlig statisk S createService (Class serviceClass) {hvis (! httpClient.interceptors (). indeholder (logning)) {httpClient.addInterceptor (logning); builder.client (httpClient.build ()); eftermontering = builder.build (); } returner retrofit.create (serviceClass); } offentlig statisk S createService (Class serviceClass, final String token) {if (token! = null) {httpClient.interceptors (). clear (); httpClient.addInterceptor (chain -> {Request original = chain.request (); Request.Builder builder1 = original.newBuilder () .header ("Authorization", token); Request request = builder1.build (); return chain.proceed) (anmodning); }); builder.client (httpClient.build ()); eftermontering = builder.build (); } returner retrofit.create (serviceClass); }}

Dette er den sidste form for vores klasse, vi kan se, hvordan vi tilføjede HttpLoggingInterceptor, og vi indstiller det til grundlæggende logning, som logger den tid, det tog at foretage anmodningen, slutpunktet, status for hver anmodning osv.

Det er vigtigt at se på, hvordan vi kontrollerer, om interceptoren findes, så vi ikke ved et uheld tilføjer den to gange.

8. Konklusion

I denne omfattende vejledning kiggede vi på det fremragende eftermonteringsbibliotek ved at fokusere på dets Sync / Async API, nogle af de bedste fremgangsmåder til modellering, godkendelse og logning.

Biblioteket kan bruges på meget komplekse og nyttige måder; for en avanceret brugssag med RxJava, se venligst denne vejledning.

Og som altid kan kildekoden findes på GitHub.