LoginSignup
21
24

More than 5 years have passed since last update.

[Android] Retrofit2 と RxJava で WEB-API の通信結果(JSON)を受け取る例

Posted at

例として Qiita API v1 を利用して、Qiitaの 新着投稿の一覧 を取得してみます。

必要なライブラリをプロジェクトへ導入

本投稿の執筆時点(2016.11.04)で最新版を導入します。

  • RxJava (ver 1.2.1)
  • RxAndroid (ver 1.2.1)
  • Gradle Retrolambda Plugin (ver 3.3.0)
  • Retrofit (ver 2.1.0)

    『Gradle Retrolambda Plugin』は Retrolambda のラムダ式を利用できるようにするものです(RxJava 利用コードが煩雑になるのを回避する為)。また Retrolambda を導入するにあたり、開発環境(OS X を想定)には Java 8 を導入してください(Oracleのサイトはこちら)。

    その他、付随して必要になる OkHttp、Gson 等も導入します。

    build.gradle
    buildscript {
        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.gradle
    apply 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 のモデルで表現します。全ての項目を定義する必要はなく、受け取りたい項目のみでよいです。

QiitaItem.java
// ...

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)は子のモデルも作成します。

QiitaItemUser.java
// ...

public class QiitaItemUser {
    @SerializedName("id")
    public int id;

    @SerializedName("url_name")
    public String urlName;

    @SerializedName("profile_image_url")
    public String profileImageUrl;
}

API の作成

Retrofit2 で API を定義します。

QiitaApiService.java
// ...

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 クラスに保持する場合は次のようにします。

MainApplication.java
// ...

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 を作成する場合は次のようにします。

Provider.jama
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 にアクセスし結果をログに出力するコードは次のようになります。

MainActivity.java
// ...

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();
    }
}

結果は次のとおりです。

スクリーンショット 2016-11-04 22.25.06.png

おわりに

今回のソースコードは GitHub に置きました。必要に応じて参照ください。
https://github.com/hkusu/android-rx-retrofit-example

21
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
24