RxJavaの概要
RxJavaは、もともとは2009年にMirosoftで.NET Frameworkの実験的なライブラリ「Reactive Extensions」(略して「Rx」)として公開され、2012年にオープンソース化されました。それを後にNetflixがJavaに移植しオープンソースとして公開したものがRxJavaになります。
現在、このReactive Extensionsを扱うライブラリはReactiveXとしてオープンソースプロジェクト化し、Javaや.NETだけでなくJavaScriptやSwiftなどさまざまなプログラミング言語に対応したライブラリを提供しています。
現在、RxJavaは次のメジャーバージョンとしてReactive StreamsのAPIに準拠したRxJava 2.xを開発中です。RxJava 2.xはもともとJava 8以降を対象にしていたのですが、途中でJava 6以降およびAndroid 2.3以降も対象に含まれるよう変更されました。こちらはもうすぐ正式リリース予定で現在発表されているスケジュールは次のようになっています。
- 2016/08/25: RC(Release Candidate)版1のリリース
- 2016/09/23: RC(Release Candidate)版2のリリース
- 2016/10/21: RC(Release Candidate)版3のリリース
- 2016/10/29: 安定版のリリース(Stable Release)
Reactive Streamsとはリアクティブにデータを処理をするための標準化を行っているもので、Java用の標準化したInterfaceを提供しています。
このReactive Streamsが提供しているInterfaceはRxJava 1.xとは異なりますが、RxJavaで用意されているReactive Streamsに変換するためのライブラリであるRxJavaReactiveStreamsを使うことでRxJava 1.xでもReactctive Streamsと連携することは可能です。ちなみに1.xでReactive Streamsに対応していない理由は、単にRxJavaの方が先に存在し、しばらく経った後でReactive Streamsが作られたためです。
このようにRxJavaは2.xのタイミングで下位互換性がない大幅な変更が入ります。しかし、RxJava 2.xのREADMEによると、しばらくの間は2.xと1.xの両方を並行して開発するそうです。そのため1.xで開発されているものを(どこかのタイミングで変えないといけないにしても)急いで2.xに変える必要はないかと思われます。また、APIが変わっても設計の本質的なところは1.xと大きくは変わらないため、1.xを知っておけば2.xについても簡単に理解できるかと思われます。今回は執筆時点ではまだRC版も出ていない状況なのでRxJava 1.xでの内容になります。連載を続けていくうちに2.x系に変わる予定です。
また、RxJavaのAPIの中には、まだ開発途中のものや実験的に入れているものもあります。それらのAPIはリリースするたびに前バージョンとの互換性がない変更が入る可能性が高いものであり、それらのAPIに依存したプログラムを実装しないほうが安全です。次のアノテーションがついているものが開発途中や実験的なAPIになります。
- @Beta
- @Experimental
そのほかにもRxJavaライブラリで内部的に使われるためのrx.internalのパッケージがあり、ここにあるAPIもリリースの際に破壊的な変更をされる可能性が高いので、このAPIに依存したプログラムも実装しないほうが安全です。
RxJavaの特徴
RxJavaの特徴の一つとして、デザインパターンの一つであるObserverパターンをうまく拡張している点があります。特にデータを生産する側とデータを消費する側に分けることで、無理なくデータストリームを扱うことができ、リアクティブプログラミングで実装できる作りになっています。
また、RxJavaは非同期の処理が行いやすい点も特徴です。開発者はまったく非同期処理について考えなくてよいわけではありませんが、Observable契約というRxJavaの開発ガイドラインに従って実装している限り、直接スレッド管理を行うような煩わしさから解放されます。また、同期処理であろうが非同期処理であろうが実装方法が大きく変わらない点もポイントの一つになります。
そして、RxJavaでは関数型プログラミングの影響を受けており、処理の多くを関数型インターフェースを受け取るメソッドを使って実現しています。このことは入力と結果のみさえ決めてさえあれば具体的な処理に関しては関数型インタフェースを実装する開発者に委ねられるため、実装上の自由度が増します。ただし、このような処理には関数型プログラミングの原則に従って副作用を発生させないような作りにしないといけません。副作用を発生させる処理とは、オブジェクトの状態を変更したり再代入を行ったりなどして、処理の外部でも参照可能なオブジェクトに対して何らかの変化を加えることです。また、ファイルやデータベースの中身を変えるようなことも副作用としてみなされます。関数型プログラミングにおいて、同じ入力を受け取ったら毎回同じ結果を返し、かつ、その入力値や処理の外部に対して何も変化を起こさないことを原則としています。RxJavaでは基本的に副作用を発生させるような処理を行うのはデータを生産する側ではなく、データを消費する側で行った方が良いでしょう。
また、この関数型インターフェースの処理において副作用を発生させないことは、複数スレッドから共有されるオブジェクトがないことになり、スレッドセーフを担保できることになります。このことはRxJava上で同期の処理を行っているものを途中で非同期に変更するとしても、すでに実装されているロジックに対しての変更が発生しません。開発者が行うことはどの部分を非同期にするのかの設定処理だけになります。