この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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 と出ました。梅雨ですね。
まとめ
以上、簡単なサンプルでした。
これらのライブラリの開発に参加している JakeWharton さんすごい!と思いました。