Androidアプリ開発 Retrofit ネットワークに接続してJsonデータを取得する

Androidアプリでネットワークに接続してREST形式のAPIを利用する場合、Retrofitを使うと便利です。
この記事は、Retrofitでネットワークに接続してJsonデータを取得する方法を記載した記事です。
環境はAndroid 7.1 (API level 25) です。
環境
- OS X El Capitan
- android sdk 25
- Oracle jdk version 1.8.0_72
- Android Studio 2.2.3
難易度
初心者向け
サンプルコード
Retrofit
Retrofitは、HTTP APIをJavaインターフェースに変更することができます。
他にもGsonを使ったPOJO変換、RxAndroidを利用した非同期処理、OkHttpの連携にも対応しています。
Google純正のライブラリではありませんが、2017年1月現在では、AndroidアプリでAPI処理を実装する場合、VolleyよりもRetrofitを利用することをオススメします。
インストール
Retrofitをインストールするには、app/build.gradleに次のように記述します。
dependencies { // Retrofit compile 'com.squareup.retrofit2:retrofit:' + rootProject.retrofitVersion }
Retrofitのバージョンはbuild.gradleに次のように記述します。
ext { retrofitVersion = "2.1.0" }
ビルド後に、Retrofitの実装が可能になります。
インターフェース実装
まず、APIをJavaインターフェースに実装します。
このサンプルでは、livedoor様が提供するお天気情報のお天気Webサービス(Livedoor Weather Web Service / LWWS)を利用します。
public interface LivedoorWeatherWebService { @GET("v1") Call<Weather> webservice(@Query("city") String city); }
■ 実装の解説
1. HTTPメソッド
RESTで利用するHTTPメソッドは、アノテーションで指定します。
@GET("v1")
HTTPメソッドのGETを@GETアノテーションで指定します。HTTPメソッドのGETはリソースを取得します。
@GETアノテーションの引数には、URIのパスを記述します。Retrofitでネットワークに接続する時は、URIのbaseUrlとパスを組み合わせたURLが利用されます。
現在のRetrofitは、URIのパスは省略できません。アプリのURIの設計は、RESTの仕様を適用した設計にしてください。
2. パラメーター
メソッドの引数でパラメーターを設定します。
接続するURLは、以下のお天気Webサービス(Livedoor Weather Web Service / LWWS)のサンプルURLです。
http://weather.livedoor.com/forecast/webservice/json/v1?city=400040
クエリが?city=400040なので
(@Query("city") String city);
とします。アノテーションにretrofit2.http.Queryを指定します。
引数の数を増やすことで多くのクエリに対応できます。もし、クエリが?city=400040&id=aaaaaaであれば
(@Query("city") String city, @Query("id") String id);
とします。
ネットワーク実装
Activityにネットワーク接続処理を実装します。
jsonデータをPOJOに変換するconverter-gsonをインストールします。
converter-gsonをインストールするには、app/build.gradleに次のように記述します。
dependencies { compile 'com.squareup.retrofit2:converter-gson:' + rootProject.retrofitVersion }
インストール後にネットワーク処理を実装します。
このサンプルでは、RxAndroidやAsyncTaskLoaderはコードが複雑になるので使いません。非同期処理は通常のスレッドで記述します。本番リリースの実装をする場合は、RxAndroidを使うのをお勧めします。
public class RetrofitActivity extends AppCompatActivity { +public static final String TAG = "RetrofitActivity"; public static final String API_URL = "http://weather.livedoor.com/forecast/webservice/json/"; private Handler handler = new Handler(); private TextView result; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_retrofit); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); result = (TextView) findViewById(R.id.result); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); } @Override public void onStart() { super.onStart(); try { Thread thread = new Thread(new Runnable() { @Override public void run() { +Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); LivedoorWeatherWebService service = retrofit.create(LivedoorWeatherWebService.class); Call<Weather> call = service.webservice("400040"); Weather weather = null; try { weather = call.execute().body(); if (weather != null) { Log.d(TAG, "weather is not null"); } else { Log.d(TAG, "weather is null"); } } catch (IOException e) { Log.d(TAG, "weather :" + e.getMessage()); e.printStackTrace(); } final Weather temp_weather = weather; handler.post(new Runnable() { @Override public void run() { if (temp_weather != null) { result.setText(String.valueOf(temp_weather.pinpointLocations.size())); } } }); } }); thread.start(); } catch (Exception e) { e.printStackTrace(); } } }
■ 実装の解説
1. Retrofitオブジェクト
BuilderパターンでRetrofitオブジェクトを作成します。
Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .build();
このBuilderパターンは、GoFのデザインパターンでなく、Effective JavaのBuilderパターンです。
GsonでPOJOに変換するConverterを設定します。
.addConverterFactory(GsonConverterFactory.create())
この実装をしないとConvertエラーが発生します。
2. Response取得
ネットワークから取得したResponseは以下のように取得します。
weather = call.execute().body();
executeメソッドでResponseオブジェクトを取得し、bodyでデータを取得します。
エラーハンドリングをする場合は、Responseオブジェクトを使用します。
Javaの力に自信がある場合は、CallAdapter.Factoryを継承したErrorAdapterクラスを作成してもいいでしょう。
ただし、CallAdapter.Factoryを継承したクラスはわかりにくいので、プロジェクトのエンジニア達の力量を考慮して実装しましょう。
3. Gson
ResponseをコンバートするGsonオブジェクトは、通常のGsonと同じです。
public class Weather { public List<Pinpointlocation> pinpointLocations; public String link; public List<Forecast> forecasts; public Copyright copyright; }
ビルド
上記のコードの動作を確認してみましょう。

APIを取得して、pinpointLocationsの数が表示されました。
結論
Retrofitは柔軟なライブラリで、GsonやRxAndroidとも連携可能です。
もちろん単体でも利用できます。
Javaの力が高ければ高いほどより洗練された使い方のできるライブラリなので、ぜひ積極的に利用してください。