Edited at

RxJavaでEventBusを作った

More than 3 years have passed since last update.


経緯

以前イベントバスとしてOttoを使用していたが、RxJavaを使ったほうがよい実装ができるので、Deprecatedとなったようだ。

以前、KotlinでRxを使ったイベントバスを作成していたので、Java化してライブラリとして公開してみることにした。


RxEventBus

https://github.com/kubode/RxEventBus

簡単な使用方法はREADMEを参照。


特徴


  • イベントクラスはEventクラスを継承する必要がある。

  • ハンドラ登録はRxEventBus#subscribe()で行う。



    • RxEventBus#subscribe()の戻り値であるSubscriptionに対してunsubscribe()することで、ハンドリングをやめる。

    • 第3パラメーターにSchedulerを渡すことで、第2パラメーターのラムダの実行スレッドを変更できる。



  • イベント送信はRxEventBus#post()で行う。


    • イベントが一度もハンドリングされなかった場合、第2パラメーターのラムダが呼ばれる。

    • ハンドラにSchedulerが指定されていた場合、ハンドラのラムダが実行されたかどうかは保証できない。

    • post時点でハンドラがあるかどうかしか判断できないため。




Usage

DaggerなどDIを使っている想定で記述する。

MainActivityでイベントを拾い、MainFragmentがイベントを投げる構成。


Android(Kotlin)での例

// イベントを定義

class MyEvent {
val answer = 42
}

// イベントを拾うActivity
class MainActivity : Activity() {
@Inject lateinit var bus: RxEventBus
private lateinit var subscription: Subscription

override fun onStart() {
super.onStart()
subscription = bus.subscribe(MyEvent.class, { Log.v(TAG, "${it.answer}") })
}

override fun onStop() {
subscription.unsubscribe()
super.onStop()
}
}

// イベントを投げるFragment
class MainFragment : Fragment() {
@Inject lateinit var bus: RxEventBus

private fun postMyEvent() {
// MainActivityによって拾われ、42がログ出力される
bus.post(MyEvent())
}

private fun postOtherEvent() {
// 拾われることがなく、Event is not handled.がログ出力される
bus.post(OtherEvent(), { Log.v(TAG, "Event is not handled.") })
}
}


追記

バージョンアップにより、Eventクラスの継承が不要になりました。


参考記事