1概要

  • このチュートリアルでは、https://github.com/kittinunf/Fuel[Fuel HTTP Library]** を見ていきます。これは、作者の言葉で言うと、Kotlin/Android用の最も簡単なHTTPネットワークライブラリです。さらに、このライブラリーはJavaでも使用できます。

ライブラリの主な機能は次のとおりです。

  • 基本的なHTTP動詞(GET、POST、DELETEなど)の両方のサポート

非同期リクエストとブロックリクエスト
** ファイルをダウンロードおよびアップロードする機能(

multipart/form-data

  • グローバル設定を管理する可能性

  • 組み込みオブジェクト直列化モジュール(Jackson、Gson、Mhosi、Forge)

  • KotlinのコルーチンモジュールとRxJava 2.xのサポート

  • ルーターのデザインパターンを簡単に設定


2依存関係

  • ライブラリはさまざまなモジュールで構成されているので、必要な機能を簡単に含めることができます。

  • RxJavaとKotlinのCoroutinesをサポートするためのモジュール

  • AndroidおよびAndroid LiveData Architectureコンポーネント用のモジュール

サポート
** オブジェクト直列化モジュールを選択できる4つのモジュール

使用する – Gson、ジャクソン、モシまたはフォージ。

このチュートリアルでは、コアモジュール、Coroutines用モジュール、RxJava、Gsonシリアライゼーションモジュールに焦点を当てます。

<dependency>
    <groupId>com.github.kittinunf.fuel</groupId>
    <artifactId>fuel</artifactId>
    <version>${fuel.version}</version>
</dependency>
<dependency>
    <groupId>com.github.kittinunf.fuel</groupId>
    <artifactId>fuel-gson</artifactId>
    <version>${fuel.version}</version>
</dependency>
<dependency>
    <groupId>com.github.kittinunf.fuel</groupId>
    <artifactId>fuel-rxjava</artifactId>
    <version>${fuel.version}</version>
</dependency>
<dependency>
    <groupId>com.github.kittinunf.fuel</groupId>
    <artifactId>fuel-coroutines</artifactId>
    <version>${fuel.version}</version>
</dependency>


JFrog Bintray

には、最新バージョンがあります。


3リクエストをする

  • リクエストを出すために、Fuelは

    String

    拡張子を提供します** さらに、そして代わりとして、それぞれのHTTP動詞のためのメソッドを持つ

    Fuel

    クラスを使うことができます。

FuelはPATCH以外のすべてのHTTP動詞をサポートします。その理由は、

Fuelの

HttpClient

は、PATCHをサポートしていない

java.net.HttpUrlConnection

のラッパーです。

この問題を回避するために、HttpClientはPATCH要求をPOST要求に変換し、

X-HTTP-Method-Override:PATCH

ヘッダーを追加します。したがって、このヘッダーをデフォルトで受け入れるようにAPIを構成する必要があります。

Fuelの機能を説明するために、http://httpbin.org/#/[httpbin.org]、単純なHTTP要求および応答サービス、およびhttps://jsonplaceholder.typicode.com[JsonPlaceholder]を使用します。 – テストとプロトタイピングのための偽のオンラインAPI。


3.1. GETリクエスト

非同期モードで簡単なHTTP

GET

リクエストを作成しましょう:

"http://httpbin.org/get".httpGet().response {
  request, response, result ->
   //response handling
}


String

の上で

httpGet()

を使うと、

Triple <Request、Response、Result>

が得られます。


  • https://github.com/kittinunf/Result



    は、操作の結果(成功または失敗)を含む機能スタイルのデータ構造です。


    後の段階で

    Result

    データ構造を再検討します。

ブロッキングモードでリクエストを行うこともできます。

val (request, response, result) = "http://httpbin.org/get"
  .httpGet().response()

返されるパラメータは非同期バージョンと同じですが、この場合、リクエストを行ったスレッドはブロックされています。

また、エンコードされたURLパラメータを使用する可能性があります。

val (request, response, result) =
  "https://jsonplaceholder.typicode.com/posts"
  .httpGet(listOf("userId" to "1")).response()
 //resolve to https://jsonplaceholder.typicode.com/posts?userId=1


httpGet()

メソッド(および他の類似のメソッド)は、URLパラメータをエンコードするための

List <Pair>

を受け取ることができます。


3.2. POSTリクエスト

GETの場合と同じ方法で、

httpPost()

を使用するか、または

Fuel

クラスの

post()

メソッドを使用して、POST要求を実行できます。

"http://httpbin.org/post".httpPost().response{
  request, response, result ->
   //response handling
}

val (request, response, result) = Fuel.post("http://httpbin.org/post")
  .response()

ボディがある場合は、JSON文字列形式の

body()

メソッドを使用してそれを配置できます。

val bodyJson = """
  { "title" : "foo",
    "body" : "bar",
    "id" : "1"
  }
"""
val (request, response, result) = Fuel.post("https://jsonplaceholder.typicode.com/posts")
  .body(bodyJson)
  .response()


3.3. 他の動詞

GETおよびPOSTと同様に、残りの各動詞にもメソッドがあります。

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


Fuel.patch()

は、

X-HTTP-Method-Override:PATCH

__ヘッダーを使用してPOSTリクエストを実行します。


4構成

  • このライブラリは、グローバル設定を管理するためのシングルトンオブジェクト

    FuelManager.instance

    を提供しています。

基本パス、いくつかのヘッダ、および共通パラメータを設定しましょう。また、いくつかのインターセプターを設定しましょう。

4.1.

BasePath


__basePath

__variableを使用して、すべてのリクエストに共通のパスを設定できます。

FuelManager.instance.basePath = "http://httpbin.org"
val (request, response, result) = "/get".httpGet().response()//will perform GET http://httpbin.org/get

4.2. ヘッダ

さらに、

baseHeaders

mapを使用して一般的なHTTPヘッダーを管理できます。

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

別の方法で、ローカルヘッダを設定したい場合は、リクエストに

header()

メソッドを使用できます。

val (request, response, result) = "/get"
  .httpGet()
  .header(mapOf("OS" to "Debian"))
  .response()

4.3. パームス

最後に、

baseParams

リストを使って共通のパラメータを設定することもできます。

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

4.4. 別のオプション

__FuelManagerで管理できるオプションは他にもたくさんあります。


  • __keystore


    whichはデフォルトで

    null__です


  • socketFactory

    はユーザによって提供されるか派生します


keystore

から

null

でない場合
**

hostnameVerifier

はデフォルトで設定されているものを使用する


HttpsURLConnection

クラス
**

requestInterceptors



responseInterceptors


  • timeout

    および

    timeoutRead

    (リクエスト用)

4.5. 要求/応答インターセプター

インターセプターに関しては、**

cUrlLoggingRequestInterceptors()、

のような提供されたリクエスト/レスポンスインターセプターを追加することができます。

FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor())

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


5レスポンス処理

以前は、操作結果(成功または失敗)を表す機能データ構造体

Result

を導入しました。


Result

を使うのは簡単です。これは、

ByteArray



__String、JSON、または一般的な

T__オブジェクトにレスポンスを含めることができるデータクラスです。

fun response(handler: (Request, Response, Result<ByteArray, FuelError>) -> Unit)
fun responseString(handler: (Request, Response, Result<String, FuelError>) -> Unit)
fun responseJson(handler: (Request, Response, Result<Json, FuelError>) -> Unit)
fun <T> responseObject(deserializer: ResponseDeserializable<T>,
  handler: (Request, Response, Result<T, FuelError>) -> Unit)

これを説明するために

String

として応答を取得しましょう。

val (request, response, result) = Fuel.post("http://httpbin.org/post")
  .responseString()
val (payload, error) = result//payload is a String

JSON形式の応答にはAndroidの依存関係が必要であることに注意してください。

<dependency>
    <groupId>com.github.kittinunf.fuel</groupId>
    <artifactId>fuel-android</artifactId>
    <version>${fuel.version}</version>
</dependency>


6. JSONシリアライゼーション/デシリアライゼーション

Fuelは、私たちのニーズと私たちが選択したJSON解析ライブラリに応じて、実装する必要がある4つの方法でレスポンスのデシリアライゼーションをサポートしています。

public fun deserialize(bytes: ByteArray): T?
public fun deserialize(inputStream: InputStream): T?
public fun deserialize(reader: Reader): T?
public fun deserialize(content: String): T?

Gsonモジュールを含めることで、オブジェクトをデシリアライズおよびシリアライズできます。

data class Post(var userId:Int,
                var id:Int,
                var title:String,
                var body:String){

    class Deserializer : ResponseDeserializable<Array<Post>> {
        override fun deserialize(content: String): Array<Post>
          = Gson().fromJson(content, Array<Post>::class.java)
    }
}

カスタムのデシリアライザを使ってオブジェクトをデシリアライズできます。

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

あるいは、Gsonの内部デシリアライザを使用するresponseObject <T>を介して:

"https://jsonplaceholder.typicode.com/posts/1"
  .httpGet().responseObject<Post> { __, __, result ->
    val post = result.component1()
  }

一方、

Gson()。toJson()

を使用して直列化することができます。

val post = Post(1, 1, "Lorem", "Lorem Ipse dolor sit amet")

val (request, response, result)
  = Fuel.post("https://jsonplaceholder.typicode.com/posts")
    .header("Content-Type" to "application/json")
    .body(Gson().toJson(post).toString())


Content-Type

を設定することが重要です。そうしないと、サーバーは別のJSONオブジェクト内のオブジェクトを受け取る可能性があります。

最終的には、同様の方法で、Jackson、Moshi、Forgeなどの依存関係を使用して実行できます。


7. ファイルをダウンロードしてアップロードする

Fuelライブラリには、ファイルをダウンロードおよびアップロードするために必要なすべての機能が含まれています。


7.1. ダウンロード


download()メソッドを使用すると、ファイルを簡単にダウンロードして、

destination()

lambda

__によって返されるファイルに保存できます。

Fuel.download("http://httpbin.org/bytes/32768")
  .destination { response, url ->
    File.createTempFile("temp", ".tmp")
  }

  • プログレスハンドラ付きのファイルをダウンロードすることもできます** :

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


7.2. アップロードする

同様に、


upload()

メソッドを使用してファイルをアップロードできます。


source()

メソッドでアップロードするファイルを示します。

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


upload()

はデフォルトでPOST動詞を使用します。別のHTTP動詞を使用したい場合は、それを指定できます。

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

さらに、ファイルのリストを受け取る

sources()

メソッドを使用して複数のファイルをアップロードできます。

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

最後に、__InputStreamからデータのBLOBをアップロードできます。

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


8 RxJavaとコルーチンのサポート

FuelはRxJavaとCoroutinesのサポートを提供しています。これは非同期のノンブロッキングコードです。


RxJava

はhttp://reactivex.io[Reactive Extensions]のJava VM実装で、非同期およびイベントベースのプログラムを作成するためのライブラリです。


Observer pattern

を拡張してデータ/イベントのシーケンスをサポートし、同期、スレッドセーフ、および並行データを気にせずに宣言的にシーケンスを組み合わせて作成できる演算子を追加構造


Kotlinのコルーチン

は、軽量のスレッドのようなものです。そのため、並行して実行し、相互に待機して通信することができます。とても安い;私たちはそれらの何千ものものを作成することができ、そして記憶に関してはほとんど支払うことができません。


8.1. RxJava

RxJava 2.xをサポートするために、Fuelは6つの拡張機能を提供します。

fun Request.rx__response(): Single<Pair<Response, Result<ByteArray, FuelError>>>
fun Request.rx__responseString(charset: Charset): Single<Pair<Response, Result<String, FuelError>>>
fun <T : Any> Request.rx__responseObject(deserializable: Deserializable<T>):
  Single<Pair<Response, Result<T, FuelError>>>
fun Request.rx__data(): Single<Result<ByteArray, FuelError>>
fun Request.rx__string(charset: Charset): Single<Result<String, FuelError>>
fun <T : Any> Request.rx__object(deserializable: Deserializable<T>): Single<Result<T, FuelError>>

すべての異なるレスポンスタイプをサポートするために、各メソッドは異なる

Single <Result <>> .

を返します。


Request

を介してより関連性のあるメソッドを呼び出すことで、「Rx」メソッドを簡単に使用できます。

 "https://jsonplaceholder.typicode.com/posts?id=1"
  .httpGet().rx__object(Post.Deserializer()).subscribe{
    res, throwable ->
      val post = res.component1()
  }


8.2. コルーチン

coroutinesモジュールで、** Fuelはコルーチンの中に応答をラップしてその結果を処理するための拡張機能を提供します。

コルーチンを使用するために、同様のAPIが利用可能になります。例えば、

responseString()



awaitStringResponse()になりました:

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


awaitObject()、awaitObjectResult()、またはawaitObjectResponse()を使用して、

String

または

ByteArray



awaitByteArrayResponse())__以外のオブジェクトを処理するための便利なメソッドも提供されます。

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

Kotlinのコルーチンは実験的なものであることを忘れないでください。


9 APIルーティング

大事なことを言い忘れましたが、ネットワークルートを処理するために、FuelはRouterデザインパターンを実装することによってサポートを提供します。

ルーターパターンでは、呼び出されたエンドポイントに応じて適切なHTTP動詞、パス、パラメーター、およびヘッダーを設定するためのメソッドの組み合わせを提供する

FuelRouting

インターフェースを使用して、APIの管理を集中化できます。

インターフェースは私達のルーターを設定することが可能である5つの特性を定義します:

sealed class PostRoutingAPI : FuelRouting {
    class posts(val userId: String, override val body: String?): PostRoutingAPI()
    class comments(val postId: String, override val body: String?): PostRoutingAPI()
    override val basePath = "https://jsonplaceholder.typicode.com"

    override val method: Method
        get() {
            return when(this) {
                is PostRoutingAPI.posts -> Method.GET
                is PostRoutingAPI.comments -> Method.GET
            }
        }

    override val path: String
        get() {
            return when(this) {
                is PostRoutingAPI.posts -> "/posts"
                is PostRoutingAPI.comments -> "/comments"
            }
        }

    override val params: List<Pair<String, Any?>>?
        get() {
            return when(this) {
                is PostRoutingAPI.posts -> listOf("userId" to this.userId)
                is PostRoutingAPI.comments -> listOf("postId" to this.postId)
            }
        }

    override val headers: Map<String, String>?
        get() {
            return null
        }
}

どのHTTP動詞を使用するかを選択するために、

method

プロパティがあります。同様に、適切なパスを選択するために

path

プロパティをオーバーライドできます。

さらに

params

プロパティを使用して、リクエストのパラメータを設定する機会があります。HTTPヘッダーを設定する必要がある場合は、それは関係のあるプロパティをオーバーライドして行うことができます。

したがって、

request()

メソッドを使用して、チュートリアル全体で使用したのと同じ方法で使用します。

Fuel.request(PostRoutingAPI.posts("1",null))
  .responseObject(Post.Deserializer()) {
      request, response, result ->
       //response handling
  }

Fuel.request(PostRoutingAPI.comments("1",null))
  .responseString { request, response, result ->
     //response handling
  }


10結論

この記事では、Kotlin用のFuel HTTPライブラリと、どんなユースケースにも役立つその便利な機能を紹介しました。

このライブラリは絶えず進化しているので、新しい機能を追跡するためにhttps://github.com/kittinunf/Fuel[GitHub]リポジトリをご覧ください。

いつものように、チュートリアルで言及されたコードスニペットの全ては私達のhttps://github.com/eugenp/tutorials/tree/master/core-kotlin[GitHubレポジトリ]にあります。