Blog

LiveData vs Flow vs RxJava

Kotlin Coroutinesの進化はすざましく、とどまるところを知りません。

状態やイベントを扱いやすくなったStateFlowSharedFlowが登場し、さらには、Lifecycleをより扱いやすくなったLifecycleOwner.addRepeatingJobLifecycleOwner.repeatOnLifecycleFlow.flowWithLifecycleが追加されました。

RoomDataStore等Jetpackの各種ライブラリでもCoroutinesが使われており、Jetpack Composeでも様々なところでCoroutinesが活用されています。

そういった中で、一部LiveDataRxJavaからCoroutinesに書き直す動きが見られ、多少混乱を招いていると感じています。

結論から言うと、現時点において積極的にCoroutinesに移行する必要性はないと考えています。

今回は、それらを比較しつつ、どういった使い分けをするのが好ましいのか私の視点からまとめます。

各々の特徴

軽く特徴を紹介します。

LiveData

LiveDataはJetpackライブラリ群の一つです。

Lifecycle を考慮したObservableであり、onStop時に自動で購読を解除してくれ、onStart時に再開をしてくれます。

値を保持することに特化しており、購読時に最新の値を通知してくれます。

そのため、イベント通知にはそのまま使うことは出来ません。

Flow

FlowKotlin Coroutinesにおいて値を複数回送信することができるInterfaceです。

状態を表現するためのStateFlowや、イベント通知のためのSharedFlowが存在します。

Kotlin Coroutinessuspend functionChannelとも当然相性が良いです。

RxJava

RxJavaReactiveXJava実装です。

ReactiveXはStreamを用いて非同期かつイベントベースのプログラミングを実現するためのライブラリです。

様々な言語で利用可能になっています。

Kotlinへの拡張を持ったRxKotlinも提供されています。

比較

それぞれを各観点から比較します。

Lifecycle

非同期処理をAndroidアプリ開発で扱うにおいて、困難なポイントにLifecycleがあります。

安易に非同期処理を扱うと、onDestory以降でViewを参照してクラッシュしたり、バックグラウンドになっているのにも関わらず不要にリソースを消費する可能性があります。

LiveData は強力にLifecycleをサポートします。

Flowに関してはlivedata-ktxにてlaunchWhenStarted等のLifecycleに従うツールが提供されています。

しかし、launchWhenStartedFlowに対して使う際は、バッファに関して注意が必要です。

それの課題を解決し、より扱いやすくしたLifecycleOwner.addRepeatingJobLifecycleOwner.repeatOnLifecycleFlow.flowWithLifecycleが登場しましたが、まだα版での提供になっています。


2021-04-06 追記


RxJavaLifecycleの対応はRxLifecycle等のサードパーティのツールを使うことで行うことが出来ます。

DataBinding

DataBindingxmlから値を参照することで、コード量を削減することが出来ます。

LiveDataDataBindingに対応しています。

FlowStateFlowを使うことでDataBindingで扱うことが出来ますが、まだCanary版のみになっています。

RxJavaDataBindingに対応しておらず、ObservableFieldLiveDataに変換する必要があります。

Javaからの利用

LiveDataRxJavaJavaから利用が可能です。

FlowKotlinからのみ利用ができ、Javaからは使うことは出来ません。 

Null安全

FlowKotlinで書かれているため、完全にNull安全です。

また、RxJavaもNull安全で扱えます。

LiveDataはLintでチェックできるようになりましたが、完全にNull安全と言えるかというと、少し難しいところがありそうです。

マルチプラットフォーム

FlowKotlin Multiplatformに対応しており、AndroidとiOSのコードを一部共通化することが可能です。

RxJavaReactiveXに準拠したRxSwiftRxDartが存在し、複数プラットフォームで似たような記述が可能です。

安定性

Flowはまだまだ成長途中のため、今後破壊的変更や大幅な機能追加も考えられます。

RxJavaLiveDataはかなり安定してきていると考えられるでしょう。

複雑性

RxJavaはオペレータの数が膨大で、かなり複雑に感じます。

FlowRxJavaと似ている部分も多いですが、一度のみ値を返すsuspend functionは非常にシンプルで、比較するとRxJavaより洗練されてると言えるでしょう。

LiveDataは複雑な機能は殆どないので、一番シンプルだと思います。

一方で、機能の豊富さという観点から見ると、逆の結果になるでしょう。

外部ツールの連携

LiveDataJetpackの各種ライブラリと相性が良く、必要なことはほぼほぼできると思います。

FlowはJetpackライブラリ群でも力を入れて支援をしています。

まだまだ発展途上ですが、今後より使いやすくなっていくことでしょう。

RxJavaは周辺ライブラリの開発も活発で、多くのツールが存在します。

一方で、Google公式によるサポートはあまり無いように感じます。

また、Kotlin Coroutinesの発展とともに、最近は下火になっている印象があります。

Jetpack Composeとの相性

LiveDataFlowRxJavaともにJetpack ComposeのStateに変換可能なオペレータが用意されています。

どれを利用していても、Jetpack Composeは利用可能です。

一方で、Coroutinesに対応したrememberCoroutineScopeLaunchedEffect等のAPIが存在し、若干Coroutinesに軍配が上がりそうです。

比較一覧

上記を表にすると、以下のようになるでしょう

 LiveDataFlowRxJava
Lifecycle
DataBinding
Javaからの利用
Null安全
マルチプラットフォーム
安定性
複雑性
機能の豊富さ
外部ツールとの連携
Jetpack Composeとの相性

使い分け

様々な観点から3つを比較してきましたが、一長一短といったところで、今の所これが良い、これは悪い、みたいなところは無いと思います。

それぞれの長所、短所を理解した上で、自分のプロジェクトにあったツールを採用することが大事です。

強いて言うのであれば、やはりFlowは今後より発展が見込めるため、新規プロジェクトで採用したり、LiveDataRxJavaから徐々に移行していくことは悪い選択肢ではないと思います。

データレイヤーでの取り扱いや、イベント通知等を含め、統一感のあるコードを書くことが可能になります。

一方で、α版でのみ提供されている機能があったり、今後大きな変更がある可能性を考えると、多少慎重になる必要があるでしょう。

また、個人的にLiveDataのシンプルさは好きです。

シンプルなプロジェクトであれば、新規プロジェクトであってもLiveDataを中心に組むと良いと思います。

RxJavaは複数プラットフォームで似た書き方ができるという大きな特徴があります。

ReactiveXの思想でコーディングするためには、RxJavaが必須です。


冒頭にも言いましたが、現段階においてCoroutinesに積極的に置き換える理由はないでしょう。

複数の書き方が入り交じるプロジェクトは、理解が困難になり、不具合も入り込みやすくなります。

引き続きLiveDataRxJavaを使い続けることは、それもまた非常に良い選択です。

選択肢が多いと悩みがちですが、各々にとって一番使いやすいツールが見つかることを祈っています。


Kotlin Coroutinesの解説本をZennにて販売しています。より詳しく学びたい方は、こちらも合わせて確認してみて下さい。

詳解 Kotlin Coroutines [2021] | Zenn

人気の記事

kotlin coroutinesのFlow, SharedFlow, StateFlowを整理する

Jetpack ComposeとKotlin Coroutinesを連携させる

Layout Composableを使って複雑なレイアウトを組む【Jetpack Compose】

テスト用Dispatcherの使い分け【Kotlin Coroutines】

Flow.combineの内部実装がすごい話

Jetpack ComposeのRippleエフェクトを深堀り、カスタマイズも