Üzemanyag HTTP könyvtár Kotlin-nal

1. Áttekintés

Ebben az oktatóanyagban megnézzük az Fuel HTTP könyvtárat, amely a szerző szavai szerint a legegyszerűbb HTTP hálózati könyvtár Kotlin / Android számára. Ezenkívül a könyvtár Java-ban is használható.

A könyvtár főbb jellemzői:

  • Támogatja az alapvető HTTP igéket (GET, POST, DELETE stb.) Aszinkron és blokkoló kéréseket egyaránt
  • Kép letöltése és feltöltése (többrészes / űrlap-adat)
  • Lehetőség a globális konfiguráció kezelésére
  • Beépített objektum-sorosító modulok (Jackson, Gson, Mhosi, Forge)
  • Támogatás Kotlin coroutines moduljához és az RxJava 2.x-hez
  • Könnyen beállíthatja a router tervezési mintáját

2. Függőségek

A könyvtár különböző modulokból áll, így könnyedén felvehetjük a szükséges funkciókat. Ezek egy része a következőket tartalmazza:

  • Egy modul az RxJava és Kotlin Coroutines támogatásához
  • Modul az Android és az Android LiveData Architecture Components támogatásához
  • Négy modul, amelyek közül kiválaszthatjuk a használni kívánt objektum sorosítási modult - Gson, Jackson, Moshi vagy Forge.

Ebben az oktatóanyagban a központi modulra, a Coroutines, az RxJava és a Gson sorosítási modulra összpontosítunk:

 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} 

A legfrissebb verziókat megtalálhatja a JFrog Bintray oldalon.

3. Kérések benyújtása

Kérés benyújtására az Fuel biztosítja a Húr kiterjesztés. Ezen felül és alternatívaként használhatjuk a Üzemanyag osztály, amely rendelkezik módszerrel minden HTTP igéhez.

Az Fuel az összes HTTP igét támogatja a PATCH kivételével. Ennek oka az Üzemanyag HttpClient egy burkoló java.net.HttpUrlConnection amely nem támogatja a PATCH-ot.

A probléma mellőzéséhez a HttpClient a PATCH kéréseket POST kéréssé alakítja, és hozzáad egy X-HTTP-Method-Override: PATCH fejlécet, ezért meg kell győződnünk arról, hogy API -ink úgy vannak-e konfigurálva, hogy alapértelmezés szerint elfogadják ezt a fejlécet.

Az Fuel funkcióinak elmagyarázása érdekében a httpbin.org-ot, egy egyszerű HTTP kérés és válasz szolgáltatást, valamint a JsonPlaceholder - egy hamis online API-t használjuk a teszteléshez és a prototípusok készítéséhez.

3.1. GET kérés

Kezdjük el létrehozni az egyszerű HTTP-t KAP kérés aszinkron módban:

"//httpbin.org/get".httpGet().response {kérés, válasz, eredmény -> // válaszkezelés}

Használata httpGet () túl egy Húr ad nekünk a Hármas.

A Eredmény egy funkcionális stílusú adatstruktúra, amely tartalmazza a művelet eredményét (siker vagy kudarc). Visszalátunk Eredmény adatstruktúra egy későbbi szakaszban.

A kérést blokkolási módban is megtehetjük:

val (kérés, válasz, eredmény) = "//httpbin.org/get" .httpGet (). válasz ()

Ne feledje, hogy a visszaadott paraméterek megegyeznek az aszinkron verzióval, de ebben az esetben a kérést végrehajtó szál blokkolva van.

Lehetőség van kódolt URL-paraméterek használatára is:

val (kérés, válasz, eredmény) = "//jsonplaceholder.typicode.com/posts" .httpGet (listOf ("userId" - "1")). response () // feloldás //jsonplaceholder.typicode.com/ hozzászólások? userId = 1 

A httpGet () módszer (és a többi hasonló) megkapja a Lista az URL-paraméterek kódolásához.

3.2. POST kérés

A POST kéréseket ugyanúgy tehetjük, mint a GET esetében, a httpPost () vagy a post () módszere Üzemanyag osztály:

"//httpbin.org/post".httpPost (). válasz {kérés, válasz, eredmény -> // válaszkezelés}
val (kérés, válasz, eredmény) = Fuel.post ("// httpbin.org/post") .response () 

Ha van testünk, át tudjuk tenni test() módszer JSON karakterlánc formátumban:

val bodyJson = "" "{" title ":" foo "," body ":" bar "," id ":" 1 "}" "" val (kérés, válasz, eredmény) = Fuel.post ("// jsonplaceholder.typicode.com/posts ") .body (bodyJson) .response ()

3.3. Más igék

Ugyanúgy, mint a GET és a POST esetében, van egy módszer a fennmaradó igék mindegyikéhez:

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

Emlékezz arra Fuel.patch () POST kérést hajt végre aX-HTTP-Method-Override: PATCH fejléc.

4. Konfiguráció

A könyvtár szállít egy egyedi tárgyat - FuelManager.instance - a globális konfiguráció kezelése.

Konfiguráljuk az alap elérési utat, néhány fejlécet és általános paramétereket. Konfiguráljunk néhány elfogót is.

4.1. BasePath

Használata basePath változóval közös utat állíthatunk be az összes kéréshez.

FuelManager.instance.basePath = "//httpbin.org" val (kérés, válasz, eredmény) = "/get".httpGet (). Response () // végrehajtja a GET //httpbin.org/get

4.2. Fejlécek

Ezenkívül a szokásos HTTP fejléceket is kezelhetjük baseHeaders térkép:

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

Alternatív módon, ha helyi fejlécet akarunk beállítani, használhatjuk a fejléc() kérésre:

val (kérés, válasz, eredmény) = "/ get" .httpGet () .header (mapOf ("OS" - "Debian")) .response ()

4.3. Params

Végül közös paramétereket is beállíthatunk a baseParams lista:

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

4.4. Egyéb opciók

Sokkal több lehetőség van, amelyeken keresztül kezelhetjük FuelManager:

  • kulcstár ami nulla alapértelmezés szerint
  • socketFactory amelyet a felhasználó biztosít vagy abból származik kulcstár ha nem az nulla
  • hostnameVerifier amely alapértelmezés szerint az által biztosított HttpsURLConnection osztály
  • requestInterceptors és válaszBevallók
  • időtúllépés és timeoutRead kérésre

4.5. Kérő / válaszoló elfogók

Az elfogókat illetően hozzáadhatunk mellékelt kérés / válasz elfogókat, mint például cUrlLoggingRequestInterceptors (), vagy meghatározhatjuk a mieinket:

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

5. Válaszkezelés

Korábban bevezettünk egy funkcionális adatstruktúrát - Eredmény - ez a művelet eredményét (siker vagy kudarc) jelenti.

Dolgozni vele Eredmény egyszerű, ez egy olyan adatosztály, amely tartalmazza a választ ByteArray, Karakterlánc, JSON, vagy általános T tárgy:

szórakoztató válasz (kezelő: (Kérés, válasz, eredmény) -> Egység) szórakoztató válaszString (kezelő: (Kérés, válasz, eredmény) -> Egység) szórakoztató válasz Json (kezelő: (Kérés, Válasz, Eredmény) -> Egység) szórakoztató válasz (deserializer: ResponseDeserializable, handler: (Request, Response, Result) -> Unit) 

Kapunk választ a-ként Húr ennek szemléltetésére:

val (kérés, válasz, eredmény) = Fuel.post ("// httpbin.org/post") .responseString () val (hasznos teher, hiba) = eredmény // a hasznos teher egy karakterlánc

Ne feledje, hogy a JSON formátumú válaszhoz Android-függőség szükséges.

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

6. JSON szerializáció / deserializáció

Az Fuel beépített támogatást nyújt a válasz dezerializálásához négy módszerrel, amelyeket szükségleteinktől és a választott JSON elemző könyvtártól függően meg kell valósítanunk:

nyilvános szórakozás deserializálása (bájtok: ByteArray): T? nyilvános szórakozás deserializálása (inputStream: InputStream): T? nyilvános mulatság deserializálása (olvasó: Olvasó): T? nyilvános szórakozás deserializálás (tartalom: String): T?

A Gson modul beépítésével deserializálhatjuk és sorosíthatjuk az objektumokat:

adatosztály Post (var userId: Int, var id: Int, var title: String, var body: String) {class Deserializer: ResponseDeserializable {felülírja a szórakoztató deserializálást (tartalom: karakterlánc): Array = Gson (). fromJson (content, Array :: class.java)}}

Az objektumokat deserializálhatjuk egyedi deserializerrel:

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

Vagy a responseObject segítségével, amely belső Gson deserializer-t használ:

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

Másrészt sorozhatjuk a Gson (). Json ():

val post = Post (1, 1, "Lorem", "Lorem Ipse dolor sit amet") val (kérés, válasz, eredmény) = Fuel.post ("// jsonplaceholder.typicode.com/posts"). header (" Content-Type "-" to application / json ") .body (Gson (). ToJson (post) .toString ())

Fontos beállítani a Tartalom típus, ellenkező esetben a szerver egy másik JSON objektumon belül fogadhatja az objektumot.

Végül hasonló módon megtehetjük Jackson, Moshi vagy Forge függőségek használatával.

7. Fájl letöltése és feltöltése

A Fuel könyvtár tartalmazza a fájlok letöltéséhez és feltöltéséhez szükséges összes funkciót.

7.1. Letöltés

A ... val Letöltés() módszerrel könnyen letölthetünk egy fájlt és elmenthetjük a rendeltetési hely() lambda:

Fuel.download ("// httpbin.org/bytes/32768") .destination {válasz, url -> File.createTempFile ("temp", ".tmp")}

Letölthetünk egy fájlt is a folyamatkezelővel:

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

7.2. Feltöltés

Ugyanúgy, segítségével feltölthetünk egy fájlt feltöltés () módszer, a feltöltendő fájlt a forrás() módszer:

Fuel.upload ("/ upload"). Forrás {request, url -> File.createTempFile ("temp", ".tmp")}

Vegye figyelembe, hogy feltöltés () alapértelmezés szerint a POST igét használja. Ha másik HTTP igét akarunk használni, megadhatjuk:

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

Sőt, több fájlt is feltölthetünk a források () módszer, amely elfogadja a fájlok listáját:

Fuel.upload ("/ post"). Források {request, url -> listOf (File.createTempFile ("temp1", ".tmp"), File.createTempFile ("temp2", ".tmp"))}

Végül feltölthetünk egy blob adatot egy InputStream:

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

8. Az RxJava és a Coroutines támogatás

Az üzemanyag támogatja az RxJava és a Coroutines programot, az asyncrhonus, nem blokkoló kód kétféle írási módját.

Az RxJava a Reactive Extensions Java virtuális gépes megvalósítása, egy aszinkron és eseményalapú programok összeállítására szolgáló könyvtár.

Kiterjeszti a Observer mintát az adatok / események szekvenciájának támogatására, és olyan operátorokat ad hozzá, amelyek deklaratív módon lehetővé teszik a szekvenciák összeállítását anélkül, hogy aggódnának a szinkronizálás, a szálbiztonság és az egyidejű adatstruktúrák miatt.

Kotlin Coroutine-jai olyanok, mint a könnyű szálak, és mint ilyenek, képesek párhuzamosan futni, várni egymásra és kommunikálni ... A legnagyobb különbség az, hogy a coroutines nagyon olcsó; ezreket hozhatunk létre, és nagyon keveset fizetünk a memória szempontjából.

8.1. RxJava

Az RxJava 2.x támogatásához az Fuel hat kiterjesztést biztosít:

fun Request.rx_response (): Egyedülálló<>> fun Request.rx_responseString (karakterkészlet: Charset): Egyetlen<>> fun Request.rx_responseObject (deserializálható: Deserializálható): Single<>> fun Request.rx_data (): Egyedülálló fun Request.rx_string (karakterkészlet: Charset): Egyetlen fun Request.rx_object (deserializálható: Deserializálható): Single

Vegye figyelembe, hogy az összes választípus támogatásához az egyes módszerek mást adnak Egyetlen.

Könnyedén használhatjuk az „Rx” módszereket, ha a relevánsabbat meghívjuk a-ra Kérés:

 "//jsonplaceholder.typicode.com/posts?id=1" .httpGet (). rx_object (Post.Deserializer ()). feliratkozás {res, dobható -> val post = res.component1 ()}

8.2. Coroutines

A coroutines modullal Az üzemanyag kiterjesztési funkciókat biztosít a válasz befogadására egy koroutin belsejében és az eredmény kezelésére.

A Coroutines használatához hasonló API-k állnak rendelkezésre, pl responseString () lett awaitStringResponse ():

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

Hasznos módszereket nyújt a (z) nem objektumok kezelésére is Húr vagy ByteArray (awaitByteArrayResponse ()) felhasználásával awaitObject (), awaitObjectResult () vagy awaitObjectResponse ():

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

Ne feledje, hogy a Kotlin Coroutines kísérleti jellegű, ami azt jelenti, hogy ez a következő kiadásokban megváltozhat.

9. API útválasztás

Végül, de nem utolsósorban, a hálózati útvonalak kezelése érdekében az üzemanyag támogatja a Router tervezési mintázatának megvalósítását.

A router mintával központosíthatjuk az API kezelését a FuelRouting interfész, amely metódusok kombinációját kínálja a megfelelő HTTP ige, elérési út, paraméterek és fejlécek beállításához a meghívott végpontnak megfelelően.

Az interfész öt tulajdonságot határoz meg, amelyekkel konfigurálható az útválasztónk:

sealed class PostRoutingAPI: FuelRouting {class posts (val userId: String, over valide body: String?): PostRoutingAPI () class comments (val postId: String, override val body: String?): PostRoutingAPI () felülbírálja val basePath = "/ /jsonplaceholder.typicode.com "felülírja a val metódust: A metódus get () {visszatér, amikor (ez) {a PostRoutingAPI.posts -> Method.GET is PostRoutingAPI.comments -> Method.GET}} felülírja a val elérési utat: String get () {return when (this) {is PostRoutingAPI.posts -> "/ posts" PostRoutingAPI.comments -> "/ comments"}} felülírja a paramétereket: Lista? get () {return when (this) {a PostRoutingAPI.posts -> listOf (a this.userId "felhasználói azonosítója" a PostRoutingAPI.comments -> listOf ("postId" ennek a.postId)}} felülírja a val fejléceket: Térkép? get () {return null}}

Annak kiválasztásához, hogy melyik HTTP igét használjuk módszer tulajdonság, hasonlóképpen felülírhatjuk a pálya tulajdonságot, hogy kiválassza a megfelelő utat.

Még inkább a params tulajdonság, lehetőségünk van a kérés paramétereinek beállítására, és ha HTTP fejléceket kell beállítanunk, akkor felülírhatjuk a vonatkozó tulajdonságot.

Ezért ugyanúgy használjuk, mint az egész oktatóanyagban a kérés() módszer:

Fuel.request (PostRoutingAPI.posts ("1", null)) .responseObject (Post.Deserializer ()) {kérés, válasz, eredmény -> // válaszkezelés}
Fuel.request (PostRoutingAPI.comments ("1", null)) .responseString {kérés, válasz, eredmény -> // válaszkezelés}

10. Következtetés

Ebben a cikkben bemutattuk a Kotlin Fuel HTTP könyvtárát és annak hasznosabb funkcióit minden felhasználási esethez.

A könyvtár folyamatosan fejlődik, ezért tekintse meg a GitHub repót - az új funkciók nyomon követése érdekében.

Szokás szerint az oktatóanyagban említett összes kódrészlet megtalálható a GitHub-adattárunkban.