Brændstof HTTP-bibliotek med Kotlin

1. Oversigt

I denne vejledning ser vi på Fuel HTTP-biblioteket, som med forfatterens ord er det nemmeste HTTP-netværksbibliotek til Kotlin / Android. Endvidere kan biblioteket også bruges i Java.

Bibliotekets hovedfunktioner inkluderer:

  • Understøttelse af grundlæggende HTTP-verber (GET, POST, SLET osv.) Både asynkrone og blokerende anmodninger
  • Evne til at downloade og uploade en fil (multipart / form-data)
  • Mulighed for at styre global konfiguration
  • Indbyggede objektsserialiseringsmoduler (Jackson, Gson, Mhosi, Forge)
  • Understøttelse af Kotlins coroutines-modul og RxJava 2.x
  • Opsæt let Routermotivmønster

2. Afhængigheder

Biblioteket er sammensat af forskellige moduler, så vi nemt kan inkludere de funktioner, vi har brug for. Nogle af disse inkluderer:

  • Et modul til RxJava og Kotlins Coroutines support
  • Et modul til Android og Android LiveData Architecture Components support
  • Fire moduler, hvorfra vi kan vælge det objektserialiseringsmodul, vi skal bruge - Gson, Jackson, Moshi eller Forge.

I denne vejledning fokuserer vi på kernemodulet, modulerne til Coroutines, RxJava og Gson-serialiseringsmodulet:

 com.github.kittinunf.fuel fuel $ {fuel.version} com.github.kittinunf.fuel fuel-gson $ {fuel.version} com.github.kittinunf.fuel fuel-rxjava $ {fuel.version} com.github. kittinunf.fuel fuel-coroutines $ {fuel.version} 

Du kan finde de nyeste versioner på JFrog Bintray.

3. At fremsætte anmodninger

For at indgive en anmodning leverer Fuel en Snor udvidelse. Derudover og som et alternativ kan vi bruge Brændstof klasse, der har en metode til hvert HTTP-verb.

Brændstof understøtter alle HTTP-verber undtagen PATCH. Årsagen er, at Brændstof HttpClient er en indpakning over java.net.HttpUrlConnection som ikke understøtter PATCH.

For at sidespore problemet konverterer HttpClient PATCH-anmodninger til en POST-anmodning og tilføjer en X-HTTP-metode-tilsidesættelse: PATCH header, så vi bliver nødt til at sikre os, at vores API'er er konfigureret til at acceptere denne header som standard.

For at forklare Brændstofs funktioner skal vi bruge httpbin.org, en simpel HTTP-anmodning og svartjeneste, og JsonPlaceholder - en falsk online API til test og prototyping.

3.1. FÅ anmodning

Lad os begynde at oprette enkel HTTP anmodning i asynkroniseringstilstand:

"//httpbin.org/get".httpGet().response {anmodning, svar, resultat -> // svarhåndtering}

Ved brug af httpFå () over en Snor giver os en Tredobbelt.

Det Resultat er en datastruktur med funktionel stil, der indeholder resultatet af operationen (succes eller fiasko). Vi besøger igen Resultat datastruktur på et senere tidspunkt.

Vi kan også stille anmodningen i blokeringsfunktion:

val (anmodning, svar, resultat) = "//httpbin.org/get" .httpGet (). svar ()

Bemærk, at de returnerede parametre er de samme som async-versionen, men i dette tilfælde er den tråd, der anmodede om, blokeret.

Der er også en mulighed for at bruge kodede webadresseparametre:

val (anmodning, svar, resultat) = "//jsonplaceholder.typicode.com/posts" .httpGet (listOf ("userId" til "1")). svar () // løsning til //jsonplaceholder.typicode.com/ indlæg? userId = 1 

Det httpFå () metode (og de andre lignende) kan modtage en Liste for at kode URL-parametre.

3.2. POST-anmodning

Vi kan foretage POST-anmodninger på samme måde som for GET ved hjælp af httpPost () eller ved hjælp af stolpe() metode til Brændstof klasse:

"//httpbin.org/post".httpPost (). svar {anmodning, svar, resultat -> // svarhåndtering}
val (anmodning, svar, resultat) = Fuel.post ("// httpbin.org/post") .respons () 

Hvis vi har en krop, kan vi gennemføre den legeme() metode i JSON strengformat:

val bodyJson = "" "{" title ":" foo "," body ":" bar "," id ":" 1 "}" "" val (anmodning, svar, resultat) = Fuel.post ("// jsonplaceholder.typicode.com/posts ") .body (bodyJson) .respons ()

3.3. Andre verb

Samme som for GET og POST, der er en metode til hver af de resterende verb:

Fuel.put ("// httpbin.org/put") Fuel.delete ("// httpbin.org/delete") Fuel.head ("// httpbin.org/get") Fuel.patch ("// httpbin .org / patch ")

Huske på, at Fuel.patch () udfører en POST-anmodning med enX-HTTP-metode-tilsidesættelse: PATCH header.

4. Konfiguration

Biblioteket leverer et enkelt objekt - FuelManager.instance - at styre global konfiguration.

Lad os konfigurere en basissti, nogle overskrifter og almindelige parametre. Lad os også konfigurere nogle interceptors.

4.1. BasePath

Ved brug af basePath variabel kan vi indstille en fælles sti for alle anmodninger.

FuelManager.instance.basePath = "//httpbin.org" val (anmodning, svar, resultat) = "/get".httpGet (). Svar () // udfører GET //httpbin.org/get

4.2. Overskrifter

Desuden kan vi administrere almindelige HTTP-headere ved hjælp af baseHeaders kort:

FuelManager.instance.baseHeaders = mapOf ("OS" til "Debian")

På en alternativ måde, hvis vi vil indstille en lokal overskrift, kan vi bruge header() metode på anmodningen:

val (anmodning, svar, resultat) = "/ get" .httpGet () .header (mapOf ("OS" til "Debian")). svar ()

4.3. Params

Endelig kan vi også indstille fælles parametre ved hjælp af baseParams liste:

FuelManager.instance.baseParams = listOf ("foo" til "bar")

4.4. Andre indstillinger

Der er mange flere muligheder, som vi kan klare gennem FuelManager:

  • keystore som er nul som standard
  • stikkontaktfabrik der leveres af brugeren eller stammer fra keystore hvis det ikke er tilfældet nul
  • værtsnavnVerifikator der er som standard indstillet til at bruge den, der leveres af HttpsURLforbindelse klasse
  • requestInterceptors og responsInterceptors
  • tiden er gået og timeoutLæs for en anmodning

4.5. Forespørgsel / reaktionsinterceptorer

Med hensyn til interceptors vi kan tilføje leverede anmodnings- / reaktionsinterceptorer som cUrlLoggingRequestInterceptors (), eller vi kan definere vores:

FuelManager.instance.addRequestInterceptor (cUrlLoggingRequestInterceptor ()) 
FuelManager.instance.addRequestInterceptor (tokenInterceptor ()) fun tokenInterceptor () = {next: (Request) -> Request -> {req: Request -> req.header (mapOf ("Authorization" to "Bearer AbCdEf123456")) next ( anmodning)}}

5. Håndtering af svar

Tidligere introducerede vi en funktionel datastruktur - Resultat - der repræsenterer driftsresultatet (succes eller fiasko).

Arbejder med Resultat er let, det er en dataklasse, der kan indeholde svaret i ByteArray, String, JSON, eller en generisk T objekt:

sjovt svar (handler: (Request, Response, Result) -> Unit) fun responseString (handler: (Request, Response, Result) -> Unit) fun responseJson (handler: (Request, Response, Result) -> Unit) fun responseObject (deserializer: ResponseDeserializable, handler: (Request, Response, Result) -> Unit) 

Lad os få et svar som en Snor for at illustrere dette:

val (anmodning, svar, resultat) = Fuel.post ("// httpbin.org/post") .responseString () val (nyttelast, fejl) = resultat // nyttelast er en streng

Bemærk, at svaret i JSON-format kræver Android-afhængigheder.

 com.github.kittinunf.fuel fuel-android $ {fuel.version} 

6. JSON Serialisering / Deserialisering

Fuel leverer indbygget support til deserialisering af svar med fire metoder, som vi skal implementere afhængigt af vores behov og det JSON-parseringsbibliotek, vi vælger:

offentlig sjov deserialize (bytes: ByteArray): T? offentlig sjov deserialize (inputStream: InputStream): T? offentlig sjov deserialize (læser: Læser): T? offentlig sjov deserialize (indhold: streng): T?

Ved at inkludere Gson-modulet kan vi deserialisere og serieisere objekter:

dataklasse Post (var userId: Int, var id: Int, var title: String, var body: String) {class Deserializer: ResponseDeserializable {override fun deserialize (indhold: String): Array = Gson (). fromJson (content, Array :: class.java)}}

Vi kan deserialisere objekter med brugerdefineret deserializer:

"//jsonplaceholder.typicode.com/posts" .httpGet (). responseObject (Post.Deserializer ()) {_, _, result -> val postsArray = result.component1 ()}

Eller via responseObject, der bruger intern Gson deserializer:

"//jsonplaceholder.typicode.com/posts/1" .httpGet (). responseObject {_, _, result -> val post = result.component1 ()}

På den anden side kan vi serialisere ved hjælp af Gson (). Til Json ():

val post = Post (1, 1, "Lorem", "Lorem Ipse dolor sit amet") val (anmodning, svar, resultat) = Fuel.post ("// jsonplaceholder.typicode.com/posts"). header (" Indholdstype "til" applikation / json "). Body (Gson (). ToJson (post) .toString ())

Det er vigtigt at indstille IndholdstypeEllers kan serveren modtage objektet inden for et andet JSON-objekt.

Til sidst kan vi på en lignende måde gøre det ved at bruge Jackson, Moshi eller Forge afhængigheder.

7. Download og upload fil

Brændstofbiblioteket indeholder alle de nødvendige funktioner til at downloade og uploade filer.

7.1. Hent

Med Hent() metode kan vi nemt downloade en fil og gemme den i den fil, der returneres af bestemmelsessted() lambda:

Brændstof.download ("// httpbin.org/bytes/32768") .destination {svar, url -> File.createTempFile ("temp", ".tmp")}

Vi kan også downloade en fil med en fremdriftshåndterer:

Brændstof.download ("// httpbin.org/bytes/327680"). Fremgang {readBytes, totalBytes -> val progress = readBytes.toFloat () / totalBytes.toFloat () // ...}

7.2. Upload

På samme måde, vi kan uploade en fil ved hjælp af upload () metode, angiver den fil, der skal uploades med kilde() metode:

Fuel.upload ("/ upload"). Kilde {anmodning, url -> File.createTempFile ("temp", ".tmp")}

Noter det upload () bruger POST-verbet som standard. Hvis vi vil bruge et andet HTTP-verb, kan vi specificere det:

Fuel.upload ("/ upload", Method.PUT) .kilde {anmodning, url -> File.createTempFile ("temp", ".tmp")}

Desuden kan vi uploade flere filer ved hjælp af kilder () metode, der accepterer en liste over filer:

Fuel.upload ("/ post"). Kilder {anmodning, url -> listOf (File.createTempFile ("temp1", ".tmp"), File.createTempFile ("temp2", ".tmp"))}

Endelig kan vi uploade en masse data fra en InputStream:

Fuel.upload ("/ post"). Blob {anmodning, url -> Blob ("filnavn.png", someObject.length, {someObject.getInputStream ()})}

8. RxJava og Coroutines support

Brændstof understøtter RxJava og Coroutines, to måder at skrive asyncrhonus, ikke-blokerende kode.

RxJava er en Java VM-implementering af Reactive Extensions, et bibliotek til komponering af asynkrone og hændelsesbaserede programmer.

Det udvider Observer-mønsteret til at understøtte sekvenser af data / begivenheder og tilføjer operatorer, der tillader komponering af sekvenser sammen erklærende uden at bekymre sig om synkronisering, trådsikkerhed og samtidige datastrukturer.

Kotlins Coroutines er som lette tråde, og som sådan kan de løbe parallelt, vente på hinanden og kommunikere ... Den største forskel er, at coroutines er meget billige; vi kan skabe tusinder af dem og betale meget lidt i hukommelse.

8.1. RxJava

For at understøtte RxJava 2.x leverer Fuel seks udvidelser:

sjov Request.rx_response (): Single<>> sjov Request.rx_responseString (charset: Charset): Single<>> sjov Request.rx_responseObject (deserializable: Deserializable): Single<>> sjov Request.rx_data (): Single sjov Request.rx_string (charset: Charset): Single sjov Request.rx_object (deserializable: Deserializable): Single

Bemærk, at for at understøtte alle forskellige svarstyper returnerer hver metode en anden Enkelt.

Vi kan let bruge “Rx” -metoder ved at påkalde den mere relevante over en Anmodning:

 "//jsonplaceholder.typicode.com/posts?id=1" .httpGet (). rx_object (Post.Deserializer ()). abonner {res, kastbar -> val post = res.component1 ()}

8.2. Coroutines

Med coroutines-modulet Brændstof giver udvidelsesfunktioner til at pakke et svar inde i en coroutine og håndtere dets resultat.

For at bruge Coroutines gøres lignende API'er tilgængelige, f.eks responsString () blev til awaitStringResponse ():

runBlocking {Fuel.get ("// httpbin.org/get"). awaitStringResponse ()}

Det giver også nyttige metoder til håndtering af andre objekter end Snor eller ByteArray (awaitByteArrayResponse ()) ved brug af awaitObject (), awaitObjectResult () eller awaitObjectResponse ():

runBlocking {Fuel.get ("// jsonplaceholder.typicode.com/posts?id=1") .awaitObjectResult (Post.Deserializer ())}

Husk, at Kotlins Coroutines er eksperimentelle, hvilket betyder, at det kan blive ændret i de kommende udgivelser.

9. API-routing

Sidst men ikke mindst, for at håndtere netværksruter, giver Fuel support ved at implementere Router-designmønsteret.

Med routermønsteret kan vi centralisere administrationen af ​​API'en ved hjælp af FuelRouting interface, som giver en kombination af metoder til at indstille det passende HTTP-verb, sti, params og headere i henhold til det kaldte slutpunkt.

Interfacet definerer fem egenskaber, hvormed det er muligt at konfigurere vores router:

forseglet klasse PostRoutingAPI: FuelRouting {klassepost (val userId: String, tilsidesættelse af valutatype: String?): PostRoutingAPI () klassekommentarer (val postId: String, tilsidesættelse af valutatype: String?): PostRoutingAPI () tilsidesættelse af val basePath = "/ /jsonplaceholder.typicode.com "tilsidesættelsesmetode: Metode get () {returner når (dette) {er PostRoutingAPI.posts -> Method.GET er PostRoutingAPI.comments -> Method.GET}} tilsidesætter val sti: String get () {return når (dette) {er PostRoutingAPI.posts -> "/ posts" er PostRoutingAPI.comments -> "/ comments"}} tilsidesætter parametre: Liste? get () {return når (dette) {er PostRoutingAPI.posts -> listOf ("userId" til this.userId) er PostRoutingAPI.comments -> listOf ("postId" til this.postId)}} tilsidesætter val overskrifter: Kort? get () {return null}}

For at vælge hvilket HTTP-verb vi skal bruge metode ejendom, ligeledes kan vi tilsidesætte sti ejendom for at vælge den rette sti.

Endnu mere med params ejendom, har vi muligheden for at indstille parametrene for anmodningen, og hvis vi har brug for at indstille HTTP-overskrifter, kan vi gøre det tilsidesat den pågældende ejendom.

Derfor bruger vi det på samme måde som vi havde over hele tutorial med anmodning() metode:

Fuel.request (PostRoutingAPI.posts ("1", null)) .responseObject (Post.Deserializer ()) {anmodning, svar, resultat -> // svarhåndtering}
Fuel.request (PostRoutingAPI.comments ("1", null)) .responseString {anmodning, svar, resultat -> // svarhåndtering}

10. Konklusion

I denne artikel har vi vist Fuel HTTP-biblioteket til Kotlin og dets mere nyttige funktioner til enhver brugssag.

Biblioteket udvikler sig konstant, så kig på deres GitHub repo - for at holde styr på nye funktioner.

Som sædvanlig kan alle kodestykker, der er nævnt i vejledningen, findes i vores GitHub-lager.


$config[zx-auto] not found$config[zx-overlay] not found