Retrofit2使ってみる

#概要
Square製のRESTクライアントライブラリであるRetrofit2の基本的な使い方とか設定とか一連の流れを備忘録的に書きます。Rxjavaには今回触れません。

#標準的な設定から使用まで
リクエストheaderの追加gsonでPOJO変換してオブジェクトを受け取るサンプルです。ついでにログ出力もします。
サンプルのAPIは[https://randomuser.me/](https://randomuser.me/)を使わせていただきました。
下記のサンプルは[https://randomuser.me/api](https://randomuser.me/api)にアクセスしてresultとinfoオブジェクトを取得してます。

gradle設定

```xml:build.gradle
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
```

Interface

```java
public interface ApiService {
    @GET("api")
    Call<RandomUserDemo> apiDemo();
}

```

モデル
※サンプルなので2階層まで

```java
public class RandomUserDemo {
    public List<Result> results;
    public Info info;
}
public class Result {
    public String gender;
    public String email;
    public int registered;
    public int dob;
    public String phone;
    public String cell;
}
public class Info {
   public String seed;
   public int results;
   public int page;
   public float version;
}
```

生成と実行

```java
        //okhttpのclient作成
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request original = chain.request();

                //header設定
                Request request = original.newBuilder()
                        .header("Accept", "application/json")
                        .method(original.method(), original.body())
                        .build();

                Response response = chain.proceed(request);

                return response;
            }
        });

        //ログ出力設定
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
        httpClient.addInterceptor(logging);

        //クライアント生成
        OkHttpClient client = httpClient.build();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://randomuser.me/")//基本のurl設定
                .addConverterFactory(GsonConverterFactory.create())//Gsonの使用
                .client(client)//カスタマイズしたokhttpのクライアントの設定
                .build();
        //Interfaceから実装を取得
        ApiService API = retrofit.create(ApiService.class);

        //実行
        API.apiDemo().enqueue(new Callback<RandomUserDemo>() {
            @Override
            public void onResponse(Call<RandomUserDemo> call, retrofit2.Response<RandomUserDemo> response) {
                if (response.isSuccessful()) {
                    //通信結果をオブジェクトで受け取る
                    RandomUserDemo demo = response.body();
                    Log.d("RETROFIT_TEST", demo.info.seed);
                } else {
                    //通信が成功したが、エラーcodeが返ってきた場合はこちら
                    Log.d("RETROFIT_TEST", "error_code" + response.code());
                }
            }

            @Override
            public void onFailure(Call<RandomUserDemo> call, Throwable t) {
                //通信が失敗した場合など
            }
        });
```

#header設定
OkhttoClientのInterceptorでheaderの追加ができます。

```java
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request original = chain.request();

                //header設定
                Request request = original.newBuilder()
                        .header("Accept", "application/json")
                        .method(original.method(), original.body())
                        .build();

                Response response = chain.proceed(request);

                return response;
            }
        });
```

またはinterface側にも書けるようです。

```java
@Headers({
        "Accept: application/json",
        "User-Agent: user_agent_hoge"
    })
@GET("/hoge")
Call<hoge> getHoge();
```
#ログ設定
gradleでokhttp3の`logging-interceptor`を追加してokhttp3のInterceptorに設定することができます。
Logの出力レベルをNONE, BASIC, HEADERS, BODYから設定することができてログの出力内容を変更できます。

```java
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
okhttpClient.addInterceptor(logging);
```

##POJO変換
Gsonだけではなく、Jackson, Moshi, Protobuf, Wireなど使うことができます。

#リクエスト
GET, POST, PUT, DELETEなどのリクエストをInterfaceにアノテーションで簡単に記述できます。
```Call<戻り値の変換Class>``` メソッド名{引数}で記述していきます。

例

```java
//Pathを引数で設定
@GET("hoge/{huga}/{piyo}")
Call<List<RandomUserDemo>> contributors(
         @Path("huga") String huga,
         @Path("piyo") String piyo
);

//クエリパラメータを引数で設定、引数にnullを入れるとパラメータは付与されなくなる
Call<List<RandomUserDemo>> getTasks(
         @Query("huga") String piyo
)

//クエリパラメータはMap<key,value>で渡すこともできる
@GET("hoge")
Call<Hoge> getNews(
         @QueryMap Map<String, String> options
);

//ポスト
@FormUrlEncoded
@POST("hoge-post")
Call<Hoge> sendFeedbackSimple(  
    @Field("huga") String huga,
    @Field("piyo") int piyo
);

```

#実行
同期
executeを使います。

```java
try {
      RandomUserDemo demo = API.apiDemo().execute().body();
} catch (IOException e) {
      e.printStackTrace();
}
```

非同期
enqueueとCallback<>を使います。

```java
API.apiDemo().enqueue(new Callback<RandomUserDemo>() {
         @Override
         public void onResponse(Call<RandomUserDemo> call, retrofit2.Response<RandomUserDemo> response) {
            RandomUserDemo demo = response.body();
         }

         @Override
         public void onFailure(Call<RandomUserDemo> call, Throwable t) {
         }
});
```