こんにちは, またくです。

Rx に業務で触れる機会があり, より理解したいなあと思い EventBus におけるイベントの受け渡しと発火の部分の再発明をしました.

RxEventBus とでもしましょうか. RxJava 2.1.3 で動作確認しています.

// RxEventBus.kt
import io.reactivex.Observable
import io.reactivex.subjects.PublishSubject

// singleton instance
object RxEventBus {

    // subscriber and observable
    private val subject = PublishSubject.create<Any>()

    // イベントを流す
    fun post(event: Any) {
        subject.onNext(event)
    }

    // ストリームを filter して購読対象を絞れるようにする
    fun <T> stream(event: Class<T>): Observable<T> = subject.hide().ofType(event)
}

そもそもやりたかったこと

Android で通知バーから情報を取得し, それが加工された結果をビューに表示.

NotificationListenerService を MVP architecture でいう View 層に置き, それに紐づく presenter で通信処理をし, その結果を activity に反映させたかった. それに伴い表示するまでの距離が遠いのでどうしようか悩んでいた. また, この結果は一時的なものであって, 保存するようなものでもない.

考えたこと

最近 EventBus を扱う機会があったなあと思い返してたら, それでいいじゃんと考えました.

特に EventBus を入れるのに何の抵抗もなかったのですが, イベントの受付と発火ができれば問題ないので, 他の所で使っていた RxJava でいいかと思い立ったのでした. 比較を入れた流れは以下のような感じです.

扱いたいイベントのクラスを作る

// 共通
data class SomethingTappedEvent(val word: String)

どこかのビュー内でイベントを受け付けられるようにする

// EventBus
@Subscribe
fun onEvent(event: SomethingTappedEvent) {
    updateView(event.word)
}

// RxEventBus
RxEventBus.stream(SomethingTappedEvent::class.java).subscribe({
    updateView(it.word)
})

イベントを発火させる

// EventBus
EventBus.getDefault().post(SomethingTappedEvent(word))

// RxEventBus
RxEventBus.post(SomethingTappedEvent(word))

おわりに

@imo さんの尽力も有り, Rx のパラダイムに業務で触れる機会が数多くなってきたおかげで興味を持ちはじめました.

Rx のパラダイムはあらゆるところで使えるものなので, 今後ここも書き換えられるな〜という所も出てきそうですが, そもそも Rx を使って書き換えるべき理由があるのかという所を踏まえて使っていきたいです.

あと, まあそうだよねという感じです.
Search - RxEventBus