Rx系において、Android向けの物にはRxJavaの他にAgeraがあります。
codelabsにAgeraがきていたので、簡単な学びがてらやってみました。
Rx系のテスト(Espresso使ったUI含む)までも書かれていたので、Rx系学ぶ人には良い材料になると思います。やっぱりRx系のテストコード書こうとしたら、 Espresso.registerIdlingResources と IdlingResource の実装を使った非同期要素を待つ、ということがかけないといけないよなーということを思いました。
対象
- codelabs
- my repository
Repositoryに対する処理
AgeraはRepositoryが1つの大事な要素だと書いていました。その中で、複雑なrepositoryを扱う場合は、以下のようになるそう。
https://codelabs.developers.google.com/codelabs/android-agera/#7
topAlbumsRepository = repositoryWithInitialValue(emptyList())
.observe(accountManager, // When the account changes...
networkStatus) // or when we get online...
.onUpdatesPer(10000) // but at most every 10 seconds...
.goTo(networkExecutor) // on the network thread...
.getFrom(albumsFetcher) // fetch albums from API...
.thenTransform(
functionFrom(String.class)
.unpack(jsonUnpacker) // unpack JSON items...
.map(jsonToAlbum) // for each album...
.filter(fiveStarRating) // filter the best...
.thenLimit(5)) // and give us the first five of those!
.compile(); // Create the repository!
この中で、例えば値の変化を観測してそのないように変化があればそれをsetTextに反映する、というところは以下のようになる。
https://github.com/KazuCocoa/agera-example-android/commit/ba11829000bf820a2c34861cfb3e5c9b071a0e78
なるほど。
テストの書きやすさや保守も考えて…
このようなAgeraの特徴の他、Rx系はcallback地獄のように入れ子にコードを書けやすいが、その反面そうするとテストしにくかったり保守が困難なコードが出来上がる。そこで、Ageraの例ではそこを対応する方法を紹介している。
https://codelabs.developers.google.com/codelabs/android-agera/#9
他、処理の分散としてメインスレッド外へ処理を逃がすために、 .goTo(mExecutor) を使った処理方法も。
Espressoも使う
最後、UI含んだテストとして、 IdlingResource の実装を使った Espresso.registerIdlingResources を利用した非同期型のこのようなRx系に対するテストコードも書いています。
https://codelabs.developers.google.com/codelabs/android-agera/#11
アニメーションOFFは毎度のご愛嬌ですね 🙂
最後に
Reactive Programmingには幾つか世代があり、Ageraはまだまだ、RxJavaは2.0で世代3~4付近だと言われていました。
https://github.com/google/agera/issues/20#issuecomment-212007539
そうはいっても、Ageraを使ったこの題材は、Androidに対してReactive Programmingを入れてテスト書くまでをざっと学ぶことができるので、やることには良い意味があるものだなーと感じました。