こんにちは。スマートフォンアプリエンジニアのまさです。
最近Androidの開発をすることになったために、同僚に助けて頂きながら勉強しました。
非同期、安全に、簡単にAPIを叩くために、ライブラリを使って
https://httpbin.org/get
を叩き、jsonデータを取得する方法をご紹介します。
まずは各種ライブラリを使えるようにするために
build.gradle
buildscript { dependencies { classpath 'me.tatarka:gradle-retrolambda:3.3.1' // 追加 } }
app/build.gradle
apply plugin: 'me.tatarka.retrolambda' // 追加 android { ... // 追加 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:25.3.1' testCompile 'junit:junit:4.12' compile 'io.reactivex:rxandroid:1.2.1' compile 'io.reactivex:rxjava:1.2.1' compile 'com.trello:rxlifecycle:1.0' compile 'com.trello:rxlifecycle-components:1.0' compile 'com.squareup.okhttp3:okhttp:3.5.0' compile 'com.google.code.gson:gson:2.8.0' compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.0.2' compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2' compile 'io.reactivex:rxandroid:1.2.1' compile 'io.reactivex:rxjava:1.2.1' retrolambdaConfig 'net.orfjackal.retrolambda:retrolambda:2.3.0' }
のように編集して、Sync Now します。 これで、今回使うライブラリを使えるようになります。
それでは適当にActivityを作って実装してみます。
package com.unifa_e.studyrx; import android.os.Bundle; import android.util.Log; import com.google.gson.annotations.SerializedName; import com.trello.rxlifecycle.components.support.RxAppCompatActivity; import okhttp3.OkHttpClient; import retrofit2.Retrofit; import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.http.GET; import rx.Observable; import rx.Observer; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; public class MainActivity extends RxAppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private static final String accessServer = "https://httpbin.org/"; private OkHttpClient mClient = new OkHttpClient(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); access(); } private void access() { requestGet() .compose(bindToLifecycle()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<Res>() { @Override public void onCompleted() { Log.d(TAG, "onCompleted"); } @Override public void onError(Throwable throwable) { Log.e(TAG, "Error : " + throwable.toString()); } @Override public void onNext(Res res) { Log.d(TAG, res.toString()); } }); } private Observable<Res> requestGet() { Retrofit retrofit = new Retrofit.Builder() .baseUrl(accessServer) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(mClient) .build(); return retrofit.create(SampleApi.class).get(); } } class Res { String url; String origin; Headers headers; @Override public String toString() { return "Res{" + "url='" + url + '\'' + ", origin='" + origin + '\'' + ", headers=" + headers + '}'; } } class Headers { @SerializedName("Host") String host; @SerializedName("Connection") String connection; @Override public String toString() { return "Headers{" + "host='" + host + '\'' + ", connection='" + connection + '\'' + '}'; } } interface SampleApi { @GET("/get") Observable<Res> get(); }
※今回は備忘録的にご紹介のため、1ファイル内にシンプルに実装しており、アクセッサやファイルを分けるなどの処理を行なっておりません。
これで実行いただくと、https://httpbin.org/get APIをrequestし、responseのjsonデータをパースしてResクラスへデータを入れ込み、ログを表示します。
簡単な説明
まずは responseに帰ってくるjsonをクラスへデータを入れ込むためのクラスである、
Res
クラスと、Headers
クラスを作成します。
@SerializedName
をつけることで、サーバサイドとメンバ変数名が違う場合には、紐付けを行うことができます。
※今回はサンプルなので、すべてのプロパティを実装していません。
getResメソッドの.addConverterFactory(GsonConverterFactory.create())
をつけることでJSONパーサを行ないます。
Rxをつかい、Observable
を返すよう実装しています。
onCreateからAPIを叩くObservable
をSubScribe
して実行します。
AppCompatActivity
ではなく、RxAppCompatActivity
を継承することで、
RxLifecycle
を .compose(bindToLifecycle())
を処理チェーンに入れるだけで、利用できます。
いちいちライフサイクルを気にせずにRxを使えるので、すでに存在しないActivityのUIにアクセスするというようなことがなくなって、安全で簡単ですね。
最後に onNext
に渡ってきたResクラスを表示させています。
如何でしたでしょうか。最初はとっつきにくかったですが、Rxを使うと見た目もよくなりますし、非同期処理の敷居が下がってとてもいいと思いました。