[Android] Retrofitを1番簡単な方法で書いてみる

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

RxとRetrofitを組み合わせて使われることが多ですが、初見だと一体何をしているのか全くわからなかった覚えがあります。
なのでRetrofitの基本的な使い方を書いて、Rxを組み合わせて使うところまで書ければと思います。

今回使うretrofitはver.1.9.0です。

ミニマムの実装

retrofitでやることは主に以下の4点です。

  • インターフェースを定義する
  • Entityを用意する(下のコードではWetherResponseクラス。このブログの最後に今回使ったサンプルを貼っています)
  • 定義したインターフェイスの実装を取得する(下のコードではMainActivityの5行目)
  • コールバック内に処理を記述する
    compile 'com.squareup.retrofit:retrofit:1.9.0'
public interface IWhetherApi {

    @GET("/data/2.5/weather?id=2172797&APPID=464b981be2248f383abxxxxxxxxxxx")
    void getWhether(Callback<WetherResponse> callback);

}
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("http://api.openweathermap.org")
                .build();
                
        restAdapter.create(IWhetherApi.class).getWhether(new Callback<WetherResponse>() {
            @Override
            public void success(WetherResponse wetherResponse, Response response) {

            }

            @Override
            public void failure(RetrofitError error) {

            }
        });

2行目でエンドポイントを指定して、5行目で定義したインターフェイスの実装を取得してgetWhether()にコールバックを渡しているだけなので、非常にシンプルですね。
IWhetherApigetアノテーションの中にPATHとクエリパラメータを全て書いています。
これだけでopenweathermapから取得したjsonをエンティティーであるWetherResponse型のオブジェクトに変換します。

ただこれだと非常に使い勝手が良くないので

public interface IWhetherApi {

    @GET("/data/2.5/weather")
    void getWhether(@Query("id") String id,
                    @Query("APPID") String appId,
                    Callback<WetherResponse> callback);

}
        String id    = "2172797";
        String appId = "464b981be2248f383abxxxxxxxxxxx";
        
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("http://api.openweathermap.org")
                .build();
                
        restAdapter.create(IWhetherApi.class).getWhether(id, appId, new Callback<WetherResponse>() {
            @Override
            public void success(WetherResponse wetherResponse, Response response) {

            }

            @Override
            public void failure(RetrofitError error) {

            }
        });

と書き換えても同じように動作します。
クエリパラメータの部分を外出ししてgetWhether()で指定できるようにした形ですね。

さらにHTTPリクエストのPATHの部分であるdata/2.5/weatherも外出しして

public interface IWhetherApi {

    @GET("/{fileName}")
    void getWhether(@Path(value = "fileName", encode = false) String fileName,
                    @Query("id") String id,
                    @Query("APPID") String appId,
                    Callback<WetherResponse> callback);

}
        String id    = "2172797";
        String appId = "464b981be2248f383abxxxxxxxxxxx";
        String path  = "data/2.5/weather";
        
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("http://api.openweathermap.org")
                .build();
                
        restAdapter.create(IWhetherApi.class).getWhether(path, id, appId,
                                                          new Callback<WetherResponse>() {
            @Override
            public void success(WetherResponse wetherResponse, Response response) {

            }

            @Override
            public void failure(RetrofitError error) {

            }
        });

このように書いても同じ動作になります。
@POSTや他のメソッドを使う時も同様の書き方が可能です。

さらに戻り値をObservableにすると

public interface IWhetherApi {

    @GET("/{fileName}")
    Observable<WetherResponse> getWhether(@Path(value = "fileName", encode = false) String fileName,
                    @Query("id") String id,
                    @Query("APPID") String appId);

}
        String id    = "2172797";
        String appId = "464b981be2248f383abxxxxxxxxxxx";
        String path  = "data/2.5/weather";
        
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("http://api.openweathermap.org")
                .build();
                
        restAdapter.create(IWhetherApi.class).getWhether(path, id, appId)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<WetherResponse>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(WetherResponse wetherResponse) {

                    }
                });

HTTPリクエストの結果がObservableとして返ってくるので、Rxのメソッドチェーンで加工やスレッドの指定、エラーハンドリングが可能になります。

以下のクラスは今回仕様したWetherResponseクラスになります。

 


public class WetherResponse {
    public Coord coord;
    @SerializedName("weather")
    public List<Weather> weathers;
    public String base;
    public Main main;
    public int visibility;
    public Wind wind;
    @SerializedName("clouds")
    public Cloud cloud;
    public int dt;
    public Sys sys;
    public int id;
    public String name;
    public int cod;

    public class Coord {
        public double lon;
        public double lat;
    }

    public class Weather {
        public int id;
        public String main;
        public String description;
        public String icon;
    }

    public class Main {
        public double temp;
        public int pressure;
        public int humidity;
        @SerializedName("temp_min")
        public double tempMin;
        @SerializedName("temp_max")
        public double tempMax;
    }
    public class Wind {
        public double speed;
        public double deg;
    }

    public class Cloud {
        public int all;
    }

    public class Sys {
        public int type;
        public int id;
        public double message;
        public String country;
        public int sunrise;
        public int sunset;
    }
}

最後に

retrofit2.0がリリースされ仕様が結構変わっているようなので、そちらについてはいずれ書こうと思います。