kobakei's blog

たまに書きます

Android開発でRxJavaを使うと嬉しいこと

RxJavaをAndroid開発で使い始めてしばらく経ったので、RxJavaを使うと何がどう変わったのかをまとめます。

※RxJavaを使ったことがない人向けの戯言です。

非同期処理の待ち合わせが書きやすい

よくある例として、2つのREST APIを並列実行して、両方の結果が帰ってきてから画面を更新する、みたいな例を考えます。

これをRxJavaを使わずに普通に書くと、

  • それぞれのAPIごとにスレッドを作る
  • CountDownLatchを使って、両方のスレッドの完了を待ち合わせる

という風になります。結構つらいです。

RxJavaでは、非同期処理を簡単に並列化できます。

// api1, api2 はAPIコールのObservable
Observable.combineLatest(api1, api2, Pair::create)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(...)

僕はCountDownLatchで3つのAPIを待ち合わせるコードを書いててウワアアア!!!ってなって、RxJavaの導入を決断しました。

画面のライフサイクルに合わせて非同期処理を止めやすい

Androidを書いてる人が一度は見たことがあるのが、非同期処理のコールバックでUI操作しようとしたけど、ユーザーがバックボタンを押したなどの理由で画面がすでにないためExceptionになるというクラッシュです。

これを回避しようとすると、コールバックが呼ばれたときに画面が破棄されていないかをチェックすることが必要になります(getActivity() != nullみたいなやつ)が、そもそも画面が破棄されたときに自動で非同期処理を止めてくれたら嬉しいですよね。RxJavaと一緒にRxLifecycleというライブラリを使えば、ActivityやFragmentの破棄時に非同期処理を中止することが簡単にできます。

myObservable
    .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) // ここ
    .subscribe();

composeの行を足すだけで、Activity/Fragmentのライフサイクルにバインドできます。

リスト操作を簡単にしたい

Javaの配列やリストはメソッドが貧弱なので、他の言語を触ったことがある人ならmapやfilterなどのメソッドが欲しくなると思います。

RxJavaを使えば、配列やリストをより簡単に扱えます。例えばこんな感じ。

List<Integer> list = Observable.just(1, 2, 3, 4, 5)
                .filter(integer -> integer % 2 == 0) // 2, 4
                .map(integer -> integer * 2) // 4, 8
                .toList() // リストへ変換
                .blockingGet(); // 同期的に取得

ただ、リスト操作を便利にするだけなら最近ではLightweight Stream APIを使うほうがスマートな気もしますし、Kotlinであれば最初からリスト関連のAPIが充実していたりもします。

まとめ

ということで、ここで書いたような課題を感じている方は、RxJava試してみるといいのではないでしょうか。 僕もまだ定番の使い方しかマスターできてませんが、考え方を一度理解すればコードが書きやすくなると思います。