pooh3's memo

Android周りを中心に。軽めに、いい加減さ50%程度で

へっぽこAndroidエンジニアがRxJavaをざっくり見通しが立つまで理解したメモ

この記事の対象はAndroidアプリを作ったことがある
Javaオブジェクト指向なコードを書ける。
RxJavaの名前は知っているけど、まだしっくりこない。
そういう人をターゲットにしたメモ。


Reactive ProgramingというかRxJavaの使い方みたいなもののさわりだと思っていただけるとありがたい。
つまりちゃんとわかるRFPやReactiveExtensionsという記事ではなく、雑にRxJavaを理解するメモ(チラシの裏)だという事を約束する。




大抵Rxの勉強をしようと資料を見るとストリームという概念の説明から入る。
これが多分最初のズッコケ部分なんじゃないか?と思う。

雑にRxJavaを理解する

これ(RxJava)の何が嬉しいかというと、オレオレなコールバック実装の部分をRxJavaにすると画一的に書きやすい(オレオレになりにくい)という点だろう。
あとはfor文もRxで書けるので、スッキリしたコードが書ける。
実際多くの人がこれを使ってコールバック部分の処理を書くとスッキリして見やすい。と言う。

何はともあれ、

RxJavaはAndroidでよくあるイベントから発生する非同期な処理を含めたデータの処理を画一的かつスッキリ書けるライブラリ

もしくは

RxJavaはメソッドチェーンを使ってデータの処理を書くやつ。(イベント処理も!)

だと思えばいい。(あくまでもライブラリとしてみた時の理解として。RxJavaを使いこなすにはReactiveProgramingを理解する必要がる。)

まずはここだけ理解して、後からよりReactiveProgramingの理解を深めればいいんじゃないかと思う。

既存の問題点


Android(というかMVX)にはそもそもコールバックヘルになりやすいという闇が存在する。

View
↓ ↑
Controller
↓ ↑
Model
MVCを使ったデータの処理のながれの例

例えばActivityで東京の天気の情報を更新しようとした場合。大抵は以下のようになる。

Activity#onCreate
↓ ↑
(Presenter#loadWeather)
↓ ↑
WeatherRepository#fetchWeatherData
↓ ↑
Infra#requestWeather
↓ ↑
(Server)

これを非同期処理としてRxJavaを使わずに書くと、無名関数を使った多重コールバック(いわゆるコールバックヘル)になるかもしれない。

コールバックヘルの解決策としてのRxJava

コールバックヘルになりやすいところをRxJavaで書くといいよ!という事なのだとまず僕は理解した。

次は実際のコードを見てみた。どうスッキリするのか確認しなくてはいけない。

まず以下のコードのloadTasksを見てみる。

https://github.com/googlesamples/android-architecture/blob/dev-todo-mvp-rxjava/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksPresenter.java

次に以下のコードのloadTasksを見てみよう。

https://github.com/googlesamples/android-architecture/blob/todo-mvp/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksPresenter.java


明らかに違うのは前者にgetTask()のメソッドにコールバックの記述がない事だ。
そして、コールバックの処理がないままデータの処理を行っている。


RxJavaを見慣れてきた側から見るとすると前者の方が圧倒的に良い。
なぜかというと
この処理を見た瞬間に

TasksRepositoryから取得したlistデータを
条件を設定してfilter()でフィルタリングし
onNext()でそのフィルタしたリストデータをprocessTasks();に渡している。

ということがすぐにわかるからだ。
つまりRxJavaを使うと見通しの良いコードが書ける。

後者だとこの流れを理解するには、コードを一度詳しく見ないといけない。
またデータ取得の成功可否の分岐としてonError()とonNext()とが同列に書かれているのも見通しが良いのだ。
成功でprocessTasks()、失敗でshowLoadingTasksError()だ。明快でわかりやすくて好きだ。


だが、RxJavaの本質、つまりReactive Programingとしての良さはここではないようだ。

RxJavaの本質って何?(雑に語る本質)

Why Functional Reactive Programming (FRP)? - Wellington Functional Programming (Wellington) - Meetup

にあるように、イベントベースプログラミングでのObseverパターンやアクターモデルパターンでは解決できていないコードが複雑になりやすいという問題に対する
代替手段としてReactiveProgramingが存在しているようだ。

つまり、データの処理の一連をスッキリ書けるだけじゃない。
スケールの手助けとなる手段としてReactiveProgramingがRxJavaの本質だと考える。

ここを理解すると、RxJavaを使ったアプリの設計やコード自体の理解も進みやすい。


再度ここでGoogleのサンプルコードのGitHubのURLを掲示する。
github.com
このコードはRxJavaの使い方を理解するには良い例だ。

データを取得する場合コールバックに当たる部分は全て

Observable<T>
※<>は全角で書いているので注意。

の形で返している。
なのでそれぞれのレイヤーでRxJavaを利用した書き方ができるのでレイヤーをまたいで
一連のデータ処理の見通しが良くなっている。

RxJavaがまだ漠然としてよく分からない

いろいろな資料見ていても、RxJavaがよく分からない。
どういう風にコードを書いていけばいいのか
サンプル見て理解できるし、そのまま同じ手順でコード書けるけど、自分一人で思うように書くにはどうすればいいのか分からない。
イベント契機に一回だけ一つのデータを取得して表示するとかどうやんの?わからない。。。

  • Observable
  • Observer
  • Action
  • Func

があるけど、どう使えばいいのかわからない。
OperatorもflatMapやfilterやもあるけど全部覚えるの大変!

そんな時、これをみてしっくりした。
Presentation: Demystifying RxJava Subscribers - Jake Wharton
(あんまり英語聞き取れないけど、動画見てると雰囲気でわかる!不思議!)

これを見ると、つまりほとんどが繋げて書ける。
そういうことなのだろう、ということがわかった。
なので、それぞれの使い方を理解し少々のテクニックを使えば、特に制約なく各処理をあっさりつないで書けてしまえるようだ。

僕はここまでで、Operatorなど全然理解していないが、RxJavaについては
ざっくりだが理解できたというか、見通しが立つようになった。


つまり、設計として組み込むレイヤーどうしの通信をさせるためのRxJavaな設計が存在し
RxJava自体にもいろんな便利な使い方が出来る。
と言うことと
RxJavaを使うと、どのレイヤーでどういう処理を書くかという点に焦点を合わせやすい。(Presenterで統一してエラー処理を書くなど)
どのレイヤーでもデータのフローに当たる部分はObservableでつないで書いてしまうことで画一的な書き方が出来、コードの見通しが全体的に立ちやすい。
とか色々。


見通しが立ったのですること

次にやることはこれだと思う。

  • RxJavaを使ったどんな設計が良い感じにスケーラブルに書けるのか例を幾つか見てみる、自分で設計してみるを繰り返す
  • 各Operatorを理解する ReactiveX - Operators


まぁ人なりに理解していく方法が違うと思うので
これがしっくりくる人とこない人がいると思う。

後で見返してもっと多くのRxJava初心者が見ても理解しややすいようにメンテしていこうと思う。