28
17

More than 5 years have passed since last update.

RxJavaで安全にイベント通知を行うためのRxRelay

Last updated at Posted at 2017-12-07

これは RxJava Advent Calendar 2017 の7日目の記事です。意外とカレンダーがスカスカしていてRxJava自体の知見はだいぶ出尽くしてしまったのかなという感じですね。

今回はRxRelayというライブラリを紹介しようと思います。
※ RxJavaについての基礎知識はあることを前提とした記事です。

RxRelayとは

  • https://github.com/JakeWharton/RxRelay
  • Android界隈では神とも呼ばれる、Jake Wharton氏によるRxJava用のライブラリ
  • Subjectより安全な、Relayという仕組みを導入するもの

RelayはSubjectから onCompleteonError を呼ぶ機能をなくしたもので、つまり onNext で値を流すことに特化したSubjectということができます。Relayは以下の性質・機能を持っています。

  • Observable および Consumer としてふるまう
  • accept で受け取った値を onNext に流す
  • ストリームが終了することはない
  • observable.subscribe(relay) はDisposableを返すので購読の解除がかんたん
  • toSerialized() を呼ぶことによりスレッドセーフなRelayを生成できる
  • AsyncSubject にあたる AsyncRelay は存在しない(ストリームの終了がないため)

これらの性質により、Relayは非RxなAPIをRx用のイベントストリームに変換するのに非常に適しています。

Relayの使いどころ

Subjectを使っていて onNext で値を流しているだけのものはRelayに置き換えてしまうことが可能です。

例えば、RxBindingを使ってMVVMのデータバインディング(AndroidのDataBinding Libraryではないです)を実装しているパターンで、ボタンのクリックイベントをViewModelに伝えたい場合、Subjectで書くと以下のようになります。

class SomeViewModel {
    val onButtonClick = PublishSubject.create<Unit>()
}

val viewModel = SomeViewModel()

button.clicks()
        .subscribe { viewModel.onButtonClick.onNext(Unit) }
        .addTo(...)

これをRelayで置き換えると、

class SomeViewModel {
    val onButtonClick = PublishRelay.create<Unit>()
}

val viewModel = SomeViewModel()

button.clicks()
        .subscribe(viewModel.onButtonClick)
        .addTo(...)

このようにスッキリ書くことができ、 onNext が排除されてデータバインディングのリアクティブ感もより高まると思います。(個人の感想です)

RxSwiftにも輸入された

RxSwiftにもRxSwift4からRelayが導入されたようです。正確には、Cocoa/UIKitとのバインディングを提供するRxCocoaの方に導入されたのですが、ほぼ標準の機能と言って良いでしょう。

参考記事:
http://tech.mercari.com/entry/2017/12/04/103247
http://tech.connehito.com/entry/variable-is-deprecated

RxJava/RxSwiftで両OS用アプリを開発している身としては非常に助かります :smiley:
RxJavaもRelayを標準機能として取り入れてもいい気がしました。

追記: RxJSにも

ちょうどこの記事を書いた数日後ですが、RxJS向けのRelayもリリースされていました。(しかもMicrosoft製)

以上です。

28
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
17