[Android] RxJava入門

昔、RxJavaに入門した頃に書いた記事が発掘されたので、このブログに投稿しておきます。KotlinではなくJavaで書かれていたり、RxJavaのバージョンが古かったりしますが、ご了承ください。

RxJavaとは

RxJavaとは、ということを考える前に、リアクティブプログラミングとは、ということについて考えなくてはなりません。RxJavaは、リアクティブプログラミングを行うためのライブラリだからです。とはいえ、リアクティブプログラミングとは、ということを考え始めるとなかなか難しいです。「RxJava リアクティブプログラミング」より引用してみます。

  • RxJavaとはJavaでリアクティブプログラミングを行うためのライブラリです。
  • リアクティブプログラミングとは、通知されてくるデータを受け取るたびに関連したプログラムが反応(リアクション)して処理を行うようにするプログラミングの考え方です。

まだよく分かりませんか?大丈夫です。やっていくうちにわかってきます。ということで、やっていきます。

RxJavaの導入

まずはAndroidのプロジェクトにRxJavaを導入していきます。app/build.gradleに以下の記述を追加します。

dependencies {
    //RxJava
    implementation 'io.reactivex.rxjava2:rxjava:2.1.9'
}

また、Java8から導入されたラムダ式を使いたいので、Java8を有効にします。

android {
    compileOptions {
        targetCompatibility 1.8
        sourceCompatibility 1.8
    }
}

以上で、AndroidでRxJavaを使う準備が整いました。

Hello RxJava

まずはRxJavaを使ってHello Worldを表示してみましょう。まずはObservableを作って、subscribeします。Observableは、io.reactivexのものを使います。こんな感じで書いてみます。書いてみたら、早速実行してみましょう。

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import io.reactivex.Observable;

public class MainActivity extends AppCompatActivity {

    private final String TAG = getClass().getSimpleName();

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

        Observable.just("Hello, RxJava!")
                .subscribe(string -> Log.d(TAG, string));
    }
}

「Hello, RxJava!」とLogcatに表示されたでしょうか?

Observableを作って、subscribeする。これがRxJavaの基本形です。

Observable#justはObservableを作るメソッドの一つで、引数にとったオブジェクトがそのままsubscribeへと順番に流れていきます。もっと多くのものを流してみましょう。

Observable.just(0, 1, 2, 3, 4)
        .subscribe(i -> Log.d(TAG, String.valueOf(i)));

0、1、2、3、4のintがsubscribeへと流れていきます。intが流れているので、String#valueOfでString型に変換しています。Observable#justは、10個までの引数をとり、それをsubscribeへと流してくれるオペレーターです。引数の型は問いません。例えば以下のコードも問題なく動作します。

Observable.just(0, 'a', 1, 'b', 2, "Hello!")
        .subscribe(__ -> {
            //do something here
        });

10個以上の要素を流したい時はどうしたらいいでしょうか?Observable#fromArrayやObservable#fromIterableを使って、配列やイテラブルから値を流します。

List list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
    list.add(i);
}

Observable.fromIterable(list)
        .subscribe(i -> Log.d(TAG, String.valueOf(i)));

これで0〜19までのintが流れていきます。ところで、上記のコードはObservable#rangeを使って、以下のように書き換えることができます。

Observable.range(0, 19)
        .subscribe(i -> Log.d(TAG, String.valueOf(i)));

この流れの中から、偶数の数字のみを取り出してみます。Observable#filterを使いましょう。Observable#filterは、ラムダ式の返り値がtrueとなるObservableのみ、次のオペレータへと流します。文字通り、値をフィルターしてくれるオペレータです。使用頻度が高いです。

Observable.range(0, 19)
        .filter(i -> i % 2 == 0)
        .subscribe(i -> Log.d(TAG, String.valueOf(i)));

次にフィルターした値を10倍にして流してみます。オペレータとして、Observable#mapを使います。Observable#mapは、ラムダ式により値を変換して、次のオペレータへと流します。

Observable.range(0, 19)
        .filter(i -> i % 2 == 0)
        .map(i -> i * 10)
        .subscribe(i -> Log.d(TAG, String.valueOf(i)));

Observable#mapは、同じ型の値を流す必要さえありません。int型をString型に変換して流してみましょう。

Observable.range(0, 19)
        .filter(i -> i % 2 == 0)
        .map(i -> i * 10)
        .map(i -> String.valueOf(i))
        .subscribe(s -> Log.d(TAG, s));

ここまでやってきたように、RxJavaのオペレータはいくつでも好きなように繋げることができます。RxJavaでは、オペレータを組み合わせることによって様々なことを簡潔なコードで実現することができます。

ところで、上記のコードは「メソッド参照」によってもう少し簡潔に書くことができます。やってみましょう。

Observable.range(0, 19)
        .filter(i -> i % 2 == 0)
        .map(i -> i * 10)
        .map(String::valueOf)
        .subscribe(s -> Log.d(TAG, s));

メソッド参照によって、簡潔な表現に書き換えることができました。

長くなってきたので、この記事はこの辺で終わりにします。Observableを作って、オペレータで流れを変え、subscribeで流す、というRxJavaのこの感覚が、少しでも伝わればいいかなと思います。

この記事の続きとして、RxJavaとRetrofitでRest APIを叩く方法について書きました。こちらも合わせて読んでいただけると嬉しいです。