ちょっと話題の記事

[Android] OkHTTP + Retrofit + RxAndroid で REST クライアントを実装する

2015.06.26

REST 処理を扱いやすく実装する

Android の REST クライアントのネットワーク処理と非同期処理について、最近流行っている OkHTTP と Retrofit と RxAndroid の組み合わせを使ってみました。これらはそれぞれ次のような機能を提供するライブラリです。

OkHTTP

  • HTTP クライアント用のライブラリ
  • HTTP2/SPDY などのプロトコルにも対応
  • HTTP ヘッダーのポリシーに準拠したローカルキャッシュの実装

Retrofit

  • REST クライアント用のライブラリ
  • アノテーションでメソッドやパラメータを指定可能
  • 通信処理は抽象化されているため自由に実装可能

RxAndroid

  • RxJava の Android 版
  • リアクティブプログラミングを Android で実装するためのライブラリ
  • イベントベースで遅延実行や非同期コールバックなどを実装可能

なお、Retrofit が OkHTTP と RxAndroid の架け橋になってくれるため、組み合わせてシンプルに記述可能になります。

導入

まずはこれら3つのライブラリを Android プロジェクトに導入しましょう。

dependencies {
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'io.reactivex:rxandroid:0.24.0'
}

実装する

準備が整いましたので、実装していきましょう。OpenWeatherMap の JSON を GET してくるサンプルを実装したいと思います。

Entity クラスの作成

今回は JSON のパーサに Gson を使います。ということでまずはエンティティクラスを作りましょう。以下は余分なプロパティを省略していますのでご容赦ください。

package jp.classmethod.sample.restsample;

import java.util.List;

public class WeatherEntity {

public String base;
public List weather;

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

}

REST インターフェースの作成

次に、REST クライアントのインターフェースを作成します。メソッド名を決めてアノテーションを追加するだけです。

package jp.classmethod.sample.restsample;

import retrofit.http.GET;
import retrofit.http.Path;
import retrofit.http.Query;
import rx.Observable;

public interface WeatherApi {

@GET("/data/2.5/{name}")
public Observable get(@Path("name") String name, @Query("q") String q);

}

非同期処理を実行する

あとは RestAdapter をインスタンス化し、Observer で Subscribe するだけです。以下は Activity でやっていますがもちろん Fragment でも構いません。

package jp.classmethod.sample.restsample;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.internal.bind.DateTypeAdapter;

import java.util.Date;

import retrofit.RestAdapter;
import retrofit.android.AndroidLog;
import retrofit.converter.GsonConverter;
import rx.Observer;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

public class MainActivity extends AppCompatActivity {

private static final String TAG = MainActivity.class.getSimpleName();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// JSONのパーサー
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.registerTypeAdapter(Date.class, new DateTypeAdapter())
.create();

// RestAdapterの生成
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint("http://api.openweathermap.org")
.setConverter(new GsonConverter(gson))
.setLogLevel(RestAdapter.LogLevel.FULL)
.setLog(new AndroidLog("=NETWORK="))
.build();

// 非同期処理の実行
adapter.create(WeatherApi.class).get("weather", "Tokyo,jp")
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@Override
public void onCompleted() {
Log.d("MainActivity", "onCompleted()");
}

@Override
public void onError(Throwable e) {
Log.e("MainActivity", "Error : " + e.toString());
}

@Override
public void onNext(WeatherEntity weather) {
Log.d("MainActivity", "onNext()");
if (weather != null) {
((TextView) findViewById(R.id.text)).setText(weather.weather.get(0).main);
}
}
});

}

}

以上で終わりです!アプリを起動してみると Rain と出ました。梅雨ですね。

retrofit

まとめ

以上、簡単なサンプルでした。

これらのライブラリの開発に参加している JakeWharton さんすごい!と思いました。