1. Qiita
  2. 投稿
  3. RxJava

OttoからRxJavaへの移行ガイド

  • 130
    いいね
  • 0
    コメント

Otto が突然メンテナンス終了したので言われたとおりRxJavaで置き換えてみた。お、いいね、でも移行するならEventBusでいいんじゃないかな、という話

経緯

_人人人人人人人人人_
> 突然のdeprecate <
 ̄Y^Y^Y^Y^Y^Y^Y^Y ̄

スクリーンショット 2016-01-21 11.20.30.png
https://github.com/square/otto/pull/181

RxJava流行っているしRxJavaで似たようなことできるからOttoのメンテナンスやめるね

えー、EventBus とかOttoみたいなpub/subとRxは別物では… と思ったのだが、

スクリーンショット 2016-01-21 11.20.49.png

gfxさんのつっこみとその後のやりとりを見て、言われたとおり参照されている記事を見てOttoを置き換えてみた

Implementing an Event Bus With RxJava - RxBus

実装

OttoのかわりにRxBusというものをつくる。

RxBus

public class RxBus {
  private final Subject<Object, Object> mBus =
      new SerializedSubject<>(PublishSubject.create());

  public RxBus() {
  }

  public void send(Object o) {
    mBus.onNext(o);
  }

  public Observable<Object> toObservable() {
    return mBus;
  }

  public boolean hasObservers() {
    return mBus.hasObservers();
  }
}

実体はこれだけ。

  • 中身はただのPublishSubject
  • ただし、スレッドセーフのためにSerializedSubjectを使用している
  • publisherは send() で送る。subscriberは toObservable() を使う

Ottoだと、BusをシングルトンでもらうためにBusProviderをつくっていたが、同じようにProviderをつくる。

public class RxBusProvider {
  private static final RxBus BUS = new RxBus();

  private RxBusProvider() {
    // No instances.
  }

  public static RxBus getInstance() {
    return BUS;
  }
}

Publisher

Publisherは、以下のような感じでイベントを送る。Ottoとほぼ同じ。

RxBusProvider.getInstance().send(new SomeEvent());

Subscriber

public class RxBusSubscriberActivity extends Activity {
  private CompositeSubscription mCompositeSubscription;

  @Override
  protected void onResume() {
    super.onResume();

    mCompositeSubscription = new CompositeSubscription();
    mCompositeSubscription.add(
        RxBusProvider.getInstance()
            .toObservable()
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(o -> {
              if (o instanceof SomeEvent) {
                // イベントが来ました
              }
            })
    );
  }

  @Override
  protected void onPause() {
    super.onPause();

    // Subscription解除
    mCompositeSubscription.unsubscribe();
  }
  • RxBusProvider.getInstance().toObservable() で取得したObservableをsubscribeする
  • Activity/Fragmentのライフサイクルにあわせてsubscribe/unsubscribeする
    • Subscriptionを管理せずに RxLifeCycle でbindしてしまうのもあり

おまけ

RxBusProvider.getInstance().hasObservers() でObserverがいるかどうかがわかるので、以下のように「アプリが表示されている場合はプッシュ通知を表示しない」機能が簡単に実装できる。

  • GCMからのプッシュ通知をイベントで送るようにする
    • Activity/Fragmentでこのイベントをsubscribe (onResumeでsubscribe, onPauseでunsubscribe) して、プッシュ通知がきたときになにか処理をする
    • GCMからプッシュ通知を受けたときにBroadcastReceiverでObserverがいるかどうかを確認する。RxBusProvider.getInstance().hasObservers() == true の場合 (=アプリが表示されている場合) はイベントは送るが、プッシュ通知は表示しない

なるほどと思いました。

まとめ

  • Ottoから「RxJavaを使った似たようなもの」への移行は比較的簡単にできそう
    • ただしRxJavaの知識が必要
  • 短期的にはOttoを使い続けるのがいいのではないだろうか
    • 十分枯れてるし
  • 中期的にはEventBusに移行、がいいのではないだろうか
    • 開発メンバーが皆RxJavaをある程度知っているのであればこのRxBusのような実装でも良い気がするがどうなんだろう。やっぱりEventBusでいいんじゃないだろうか

参照記事など

Subjectとは? Hot/Coldとは? などは以下の記事が参考になりました