例として Qiita API v1 を利用して、Qiitaの 新着投稿の一覧 を取得してみます。
必要なライブラリをプロジェクトへ導入
本投稿の執筆時点(2016.11.04)で最新版を導入します。
-
『Gradle Retrolambda Plugin』は Retrolambda のラムダ式を利用できるようにするものです(RxJava 利用コードが煩雑になるのを回避する為)。また Retrolambda を導入するにあたり、開発環境(OS X を想定)には Java 8 を導入してください(Oracleのサイトはこちら)。
その他、付随して必要になる OkHttp、Gson 等も導入します。
build.gradlebuildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.1' + classpath 'me.tatarka:gradle-retrolambda:3.3.0' } } allprojects { repositories { jcenter() } } task clean(type: Delete) { delete rootProject.buildDir }
app/build.gradleapply plugin: 'com.android.application' + apply plugin: 'me.tatarka.retrolambda' android { compileSdkVersion 24 buildToolsVersion "24.0.3" defaultConfig { applicationId "io.github.hkusu.rxRetrofit" minSdkVersion 21 targetSdkVersion 23 versionCode 1 versionName "0.0.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:24.2.1' compile "com.android.support:support-v4:24.2.1" compile "com.android.support:support-annotations:24.2.1" + compile 'io.reactivex:rxjava:1.2.1' + compile 'io.reactivex:rxandroid:1.2.1' + compile 'com.squareup.retrofit2:retrofit:2.1.0' + compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' + compile 'com.squareup.retrofit2:converter-gson:2.1.0' + compile 'com.google.code.gson:gson:2.7' + compile 'com.squareup.okhttp3:okhttp:3.4.1' testCompile 'junit:junit:4.12' }
Gson モデルの作成
API のレスポンス(JSON形式)で受け取るデータを Gson のモデルで表現します。全ての項目を定義する必要はなく、受け取りたい項目のみでよいです。
// ...
public class QiitaItem {
@SerializedName("id")
public int id;
@SerializedName("uuid")
public String uuid;
@SerializedName("title")
public String title;
@SerializedName("url")
public String url;
@SerializedName("user")
public QiitaItemUser user;
}
入れ子の場合(上記でいうとuser
)は子のモデルも作成します。
// ...
public class QiitaItemUser {
@SerializedName("id")
public int id;
@SerializedName("url_name")
public String urlName;
@SerializedName("profile_image_url")
public String profileImageUrl;
}
API の作成
Retrofit2 で API を定義します。
// ...
public interface QiitaApiService {
@GET("items?per_page=10&page=1")
Observable<List<QiitaItem>> items();
// 他に API があればここに並べる
}
この例だと item()
メソッドで Qiita API の items?per_page=10&page=1
に HTTP の GET
メソッドでアクセスし、戻り値は RxJava の Observable 型(中身は先程 Gson モデルで定義した QiitaItem
の List)です。
この API サービスのインスタンス化するには次のようにします。API の基準 URL はここで指定します。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://qiita.com/api/v1/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
qiitaApiService = retrofit.create(QiitaApiService.class);
この API サービスのインスタンス(qiitaApiService
)は何度も作成するのは無駄なので、アプリケーション全体で使いまわすようにします。方法は色々ありますが(自分なら Dagger2 を使いますが)、例えば Application
クラスに保持する場合は次のようにします。
// ...
public class MainApplication extends Application {
private QiitaApiService qiitaApiService = null;
@Override
public void onCreate() {
super.onCreate();
}
public QiitaApiService getQiitaApiService() {
if (qiitaApiService == null) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://qiita.com/api/v1/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
qiitaApiService = retrofit.create(QiitaApiService.class);
}
return qiitaApiService;
}
}
もしくは static フィールドと static メソッドでインスンタンスの保持と配信をするような Provider を作成する場合は次のようにします。
public class Provider {
private static QiitaApiService qiitaApiService = null;
public static QiitaApiService provideQiitaApiService() {
if (qiitaApiService == null) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://qiita.com/api/v1/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
qiitaApiService = retrofit.create(QiitaApiService.class);
}
return qiitaApiService;
}
}
API の利用
例えば Activity の onResume()
で API にアクセスし結果をログに出力するコードは次のようになります。
// ...
public class MainActivity extends AppCompatActivity {
private QiitaApiService qiitaApiService;
private Subscription subscription;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
qiitaApiService = ((MainApplication) getApplication()).getQiitaApiService();
}
@Override
protected void onResume() {
super.onResume();
// Qiitaの新着アイテムを取得
subscription = qiitaApiService.items()
.subscribeOn(Schedulers.io()) // バックグランドで実行
.observeOn(AndroidSchedulers.mainThread()) // UIスレッドで購読
.subscribe(aQiitaItemList -> {
// ログにタイトルを出力
for (QiitaItem qiitaItem: aQiitaItemList) {
Log.d("QiitaItem:", qiitaItem.title);
}
});
}
@Override
protected void onPause() {
super.onPause();
// 購読解除
subscription.unsubscribe();
}
}
結果は次のとおりです。
おわりに
今回のソースコードは GitHub に置きました。必要に応じて参照ください。
⇒ https://github.com/hkusu/android-rx-retrofit-example