今回はRetrofitの基本的な使い方について書きたいと思います。
Android開発でAPI連携を行う場合に必ずと言っていいほど使うと思います。たまにハマってしまうので、まとめようかと思います。
Retrofitは、APIから取得するJSONデータを、オブジェクトにしてアクセスできるようにするまでを面倒見てくれるHTTP clientです。
通信はOkhttp
というライブラリを合わせて使うことが多いと思います。今回はOkHttp
の説明は省きたいと思います。
では使い方をみていきましょう!!
Retrofitの使い方
使い方はかなりシンプルです。
- gradleでの設定追加
- Interface実装
- HttpClient実装
gradleの設定追加に関しては下記自分が書いた記事をみてください!
今回は2の「Interface実装」を少し詳しくみていきます。
リクエストメソッド
下記が1番シンプルなパターンです。
@GET("api") val api(): Call<Response>
上記の場合だと、実行されるAPIは「http://○○○○○○○○○○○○○○○○/api」という形になります。ここでは説明を省いてましたが、URLのapi以前はHttpClient実装で定義することが多いと思います。
@GET
をつけることでGETメソッドであることを明示します。
また、下記のように直接パラメータをつけることも可能です。
@GET("api/list?sort=desc") val api(): Call<Response>
URLを動的に扱う
URLを動的に扱う場合は下記のようにします。
@GET("api/{id}/list") fun getList(@Path("id") groupId : Int) : Call<Response>
{}で囲んで命名し、@Path
をNameと一緒に定義することで渡したパラメータがURLパスの中に代入されます。
今回の場合はidを動的にしてURLでその値を受け取ってリクエストを作ります。
また、@Path
の他に@Query
というものもあります。
@GET("api") fun getList(@Query("id") groupId : Int) : Call<Response>
こうするとAPIのURLは「http://○○○○○○○○○○○○○○○○/api?id=○○」になります。後ろに?
をつけてパラメータを追加する形になります。
GETリクエストで多い形式です。
リクエストボディ
先ほどのURLの末尾に?
をつけてパラメータを追加する物とは別に、インスタンスがもつ要素をJson形式に変換してパラメータに追加する形式があります。
その場合はインスタンスクラスを引数にするインターフェースを用意し、@Body
をつけます。
これはPOSTやPUTなどでよく使われます。
場合によりますが、GETとPOSTで@Body
を使うか@Query
を使うか変わってくるので確認しましょう!これで自分は苦労しました。(今回はこれが理由で記事書いてます)
@POST("users/create") fun createUser(@Body user: User): Call<Response>;
Header
RetorfitではHeaderを定義するることもできます。
@Headers({ "Accept: application/json", "token: AAAAAAA" }) @GET("api") val api(): Call<Response>
単体指定、複数指定も可能です。ただ、動的な値を指定する場合は悪鬼のようにするかOkHttp
のIntercepterで動的に作成することになると思います。
@GET("api") val api(@Header("token") token: String): Call<Response> // もしくはマップ形式で渡すことも可能 @GET("user") val api(@HeaderMap Map<String, String> headers): Call<Response>
FORM ENCODED
application/x-www-form-urlencoded
(key=value) 形式に自動で変換して欲しい場合は@FormUrlEncoded
と@Filed
を使います。
@FormUrlEncoded @POST("user/edit") val updateUser(@Field("first_name") firstName :String, @Field("last_name") lastName :String): Call<Response>
@FormUrlEncoded
はUTF-8 でエンコードしてしまうので、他の文字コードで POST する必要がある場合は@Body
を使う必要があります。
MULTIPART
Retrofitは画像やファイルなどマルチパートなデータ送信にも対応しています。
次のように@Multipart
をつけ、送りたいデータには@Part
あるいは@PartMap
をつけます。
@Multipart @PUT("user/photo") fun updateUser(@Part("photo") photo: RequestBody): Call<User>
ただ、@Multipart
と@FormUrlEncoded
はContent-Typeが矛盾するので併用できません。
HttpClient実装
最後にHttpClientの実装についても軽く触れます。 Retrofitのフレームワークを使い、APIを定義したInterfaceをインスタンス化します。
val retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); val service = retrofit.create(GitHubService.class)
このserviceがInterface(APIを定義したもの)であり、実際にAPIコールを行う際に利用します。
また、RetrofitではhttpClientの実装としてokhttpを使用するのが一般的ですが、自分でOkHttpのインスタンスを指定することが出来ます。
val okHttpClient = OkHttpClient.Builder() .addInterceptor(new HttpLoggingInterceptor().setLevel(Level.BODY)) .build(); val retrofit = Retrofit.Builder() .baseUrl("https://api.github.com/") .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build(); val service = retrofit.create(GitHubService.class)
今回はログ出力の設定を入れているだけですが、ヘッダーの設定やその他いろんな設定を加えることができます。
Gsonについて
HttpClient実装でGsonConverterFactory.create()
というファクトリーメソッドを設定しました。
今回Gson
を使用するので、ファクトリーメソッドを設定しないとJSONをオブジェクトに変換できないためです。
ここでGsonについて補足しようと思います。
Gsonは、Googleが提供するJSONデータとオブジェクトを相互に変換するためのライブラリです。 具体的には、JSONデータをレスポンスのクラスにマッピングした状態に変換するときに使用するクラスです。
オブジェクトをマッピングする場合には次のようにして使用します。
data class TestData( var firstName: String, var secondName: String ) val strJson = "{firstName=A, secondName=B}" val testData = Gson().fromJson(strJson, TestData::class.java) val firstName = testData.firstName
リストをマッピングする場合には次のように使用します。
val strJson = "[{firstName=A, secondName=B},{firstName=AAA,secondName=BBB}]" val listType = object : TypeToken<List<TestData>>() {}.type val testDataList = Gson().fromJson<List<TestData>>(strJson, listType) val firstName = testDataList[0].firstName
実際にAPIで使用する場合にはマッピングするクラスを指定すればいいだけなので、上記のような処理は基本的には行わないですが、 Jsonのレスポンスをマッピングする場合には上記のようにしてマッピングをするというのを覚えておくといいかもしれません。