Androidアプリ開発 Rxjava2 時刻表示アプリを作成してFlowableを理解する

2017年03月05日(編集2017年03月05日)
このエントリーをはてなブックマークに追加

Androidアプリ開発でRxJava2を使うと、UIの実装が便利になります。
この記事は、AndroidアプリでRxJava2のFlowableの使い方を記載した記事です。

環境はAndroid 7.1 (API level 25) です。

環境

  • OS X El Capitan
  • android sdk 25
  • Oracle jdk version 1.8.0_72
  • Android Studio 2.2.3
  • Rxjava 2.0.1

難易度

中級者向け

サンプルコード

Android-Rxjava2-Demo

Rxjava2

Rxjavaは、Javaでリアクティブプログラミングをするためのライブラリです。
リアクティブプログラミングは、送られてきたデータを受け取るたびに反応して処理をするプログラミングです。

Rxjavaはデータを作成して通知する生産者(Publisher)と、データを受け取り処理を行う消費者(Subscriber)で構成されています。

Rxjava2ではObservableとほぼ同じ機能を提供するFlowableクラスが新たに導入されました。両者の違いは、Backpressure機能の有無です。Backpressureについてはここで詳しく説明しています。

インストール

Rxjavaのインストールの設定をgradleにします。
Rxjavaのバージョンはbuild.gradleに次のように記述します。

{project_folder}/app/build.gradle
ext {
    buildToolsVersion = "25.0.2"
    supportLibVersion = "25.1.1"
    rxandroidVersion = "2.0.1"
    rxjavaVersion = "2.0.1"
    rxjavaOptional = "1.1.0"
    threetenabp = "1.0.5"
}
          

Rxjavaの情報は、app/build.gradleに次のように記述します。

{project_folder}/app/build.gradle
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:' + rootProject.supportLibVersion
    compile 'com.android.support:design:' + rootProject.supportLibVersion
    compile 'com.android.support:support-v4:' + rootProject.supportLibVersion

    compile 'io.reactivex.rxjava2:rxandroid:' + rootProject.rxandroidVersion
    // Because RxAndroid releases are few and far between, it is recommended you also
    // explicitly depend on RxJava's latest version for bug fixes and new features.
    compile 'io.reactivex.rxjava2:rxjava:' + rootProject.rxjavaVersion
    // https://github.com/JakeWharton/ThreeTenABP
    compile 'com.jakewharton.threetenabp:threetenabp:' + rootProject.threetenabp
    testCompile 'junit:junit:4.12'
}
          

ビルド後に、RxJava2の実装が可能になります。

アプリ設計

サンプルとして、以下のような時刻表示アプリを作成します。

fig1. アプリ画面

Rxjava2のFlowableを使って現在の時間を表示するだけのシンプルなアプリです。

実装

画面のベースになるActivityを作成します。
クラス名はTimeDisplayActivityにします。

{project_folder}/TimeDisplayActivity.java
public class TimeDisplayActivity extends AppCompatActivity {
    private static final String TAG = "TimeDisplayActivity";
    private TextView time;
    private Disposable disposable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_time_display);
        AndroidThreeTen.init(this);

        time = (TextView) findViewById(R.id.timer);

       +// 生産者を作成(create Producer)
        disposable = Flowable.interval(1000L, TimeUnit.MILLISECONDS)
                // スレッド(thread)
                .observeOn(AndroidSchedulers.mainThread())
                // 購読(subscribe)
                .subscribe(aLong -> {
                    updateTimeView();
                });
    }

    /**
     * update TimeTextView
     * Timeのviewを更新する
     */
    private void updateTimeView() {
       +LocalDateTime current = LocalDateTime.now();
        StringBuffer str = new StringBuffer();
        str.append(current.getHour() + " : " + current.getMinute() + " : " + current.getSecond());
        time.setText(str.toString());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
    }
}
        

■ 実装の解説

1. Flowable

Flowableは、Publisherを実装した生産者のクラスです。
Rxjava2から導入されたクラスで、Rxjava1から存在するObservableとほとんど同じ機能を提供します。 Observableとの違いは、Backpressureの機能が利用できることです。

Flowable
        

また、Flowableはcoldな生産者です。coldな生産者では、subscribeされるたびにデータを通知するストリームが作成されます。Rxjavaでは、基本的にcoldな生産者になります。

2. Backpressure

Backpressureは、データを通知する量をコントロールする機能です。Rxjava2では、FlowableだけがBackpressureの機能を持っています。Observableにはありません。

この機能は、データの通知スピードが受け取り側の処理より早い場合に利用します。通知スピードが受け取り側の処理より早い場合、受け取り側の処理が間に合わなくて、処理待ちのデータがたまってしまいます。これを解決するのがBackpressureです。

Rxjava2から、ObservableでBackpressureの機能が利用できなくなったことも認識しておきましょう。Backpressureの機能を利用していない場合は、FlowableとObservableの違いを気にする必要はありません。

3. interval

intervalメソッドは引数に指定した間隔で、Flowableオブジェクト(生産者)を発行します。

Flowable.interval(1000L, TimeUnit.MILLISECONDS)
        

4. observeOn

observeOnメソッドは、データを受け取った側(消費者)の処理を、どのようなSchedule上で行うのかを設定するメソッドです。

observeOn(AndroidSchedulers.mainThread())
        

observeOnメソッドが指定したSchedulerが設定したスレッド上で、それ以降の処理を行うようになります。
上記の処理は、データを受け取る側(消費者)が、AndroidのUIの場合に利用します。このサンプルでは、データを受け取るのがUIのTextViewなので、AndroidSchedulers.mainThread()を使います。このメソッドを呼びださないと、Only the original thread that created a view hierarchy can touch its viewsが発生します。

5. subscribe

Flowable(生産者)が通知したデータを、消費者が購読します。

.subscribe(aLong -> {
    updateTimeView();
});
        

このサンプルの購読する消費者はTextViewです。

Rxjava2では、ほぼ同じ機能であるsubscribeWithメソッドも使用できます。このサンプルコードでは不要なので、使用しません。

6. LocalDateTime

Java8から導入された日付クラスです。まだAndroidでは利用できないので、バックポートで取り入れています。

AndroidThreeTen.init(this);

LocalDateTime current = LocalDateTime.now();
StringBuffer str = new StringBuffer();
str.append(current.getHour() + " : " + current.getMinute() + " : " + current.getSecond());
        

7. Disposable

購読を解除します。

if (disposable != null && !disposable.isDisposed()) {
    disposable.dispose();
}
        

isDisposed()メソッドで購読状態を判定してから、購読を解除します。

ビルド

上記のコードビルドして動作を確認します。

fig2. アプリ画面

1秒間隔で更新される時刻が表示できました。

結論

RxJava2を使うと少ないコード量で通知と受信の実装が可能です。理解するまでが大変ですが、使ってみてください。

関連記事

タグ検索で調べてみよう

Android7.1 RxJava RxJava2