読者です 読者をやめる 読者になる 読者になる

Androidはワンツーパンチ 三歩進んで二歩下がる

Android卵プログラマーの記録ブログ

EventBusライブラリを使っていた箇所をRxJavaで書き換えたよ

Android

もう2年前になりますが、Androidコンポーネント間でイベントを送受信する方法としてEventBusというライブラリを使ってみた記事を書きました。
sakura-bird1.hatenablog.com


似たようなライブラリにOttoというものがありますが、こちらはRxJava・RxAndroidで代替できるためDeprecatedになっています。EventBusライブラリを使ったコードももちろんRxJavaで代替できます。
今更感はありますが、上記記事中のサンプルコードをRxJavaを使って書き換えましたのでご紹介します。
RxJavaの理解が甘かったりするかと思いますが、まろやかなツッコミをいただければ嬉しいです(●´ϖ`●)
RxJavaは1.x系と2.x系で割りと変化していますがこのエントリでは2.x系でコードを書いています。

サンプルコードの仕様

上記のエントリーで作ったサンプルプロジェクトをRxJavaを使ってリファクタリングしています。
(環境のアップデートをしていたり画面のボタンの文言を変えている部分が若干ありますが、機能的には同じものです)
github.com

このサンプルプロジェクトで何をしているかといいますと
・ワーカースレッドからUIスレッドへのイベント通知
・BroadcastReceiver内からFragmentへイベント通知
を行い、イベントを受け取ったFragment内でイベントオブジェクトがもっているStringを画面に表示しています。

画面の動き的には、ボタンを押すと画面に文字が表示されたり、電源のコードを抜き差しすると画面に文字が表示されるという単純なものです。
今回の書き換え時にJackを有効にしてJava8を使用しています。

サンプルコードのGithubリポジトリ

書き換え前のコード全体はこちらです。
GitHub - sakurabird/Android-MyExamEventBus at b1d63ff6533938fab3d95efd050481815e7bb0a1
書き換え後のコード全体はこちらです。
GitHub - sakurabird/Android-MyExamEventBus at use-RxJava-instead-eventbus

実装

イベント発生時に投げるオブジェクトはEventBus版、RxJava版共に共通です。

public class ThreadEvent {
    public final String message;

    public ThreadEvent(@NonNull String message) {
        this.message = message;
    }
}

RxJava版ではイベント送信用のパイプラインになるクラスを作成します。

public class RxBus {

    private static RxBus instance;

    private PublishSubject<Object> subject = PublishSubject.create();

    public static RxBus instanceOf() {
        if (instance == null) {
            instance = new RxBus();
        }
        return instance;
    }

    public void post(Object object) {
        subject.onNext(object);
    }

    public Observable<Object> getObservable() {
        return subject;
    }
}

イベント発生時にイベントオブジェクトを投げる箇所

EventBus版では次のようになります。

EventBus.getDefault().post(new ThreadEvent("スレッドからの通知"));

RxJava版では次のようになります。

RxBus.instanceOf().post(new ThreadEvent("スレッドからの通知"));

イベント受信部分の実装

EventBus版では次のようになります。

       @Override
        public void onStart() {
            super.onStart();
            // EventBusを登録する
            EventBus.getDefault().register(this);
        }

        @Override
        public void onStop() {
            // EventBusを登録解除する
            EventBus.getDefault().unregister(this);
            super.onStop();
        }

ーーー中略ーーー

        public void onEventMainThread(@NonNull final ThreadEvent event){
            ((TextView) getView().findViewById(R.id.TextView)).setText(event.message);
            Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
        }

RxJava版では次のようになります。

        @Override
        public void onStart() {
            super.onStart();

            // イベント監視をスタートする
            RxBus.instanceOf().getObservable()
                    .subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(mThreadEventObserver);

        @Override
        public void onDestroy() {
            super.onDestroy();
            mThreadEventObserver.onComplete();
        }

ーーー中略ーーー

        // Subscriberは再利用できないので、Observerを使う
        private Observer<? super Object> mThreadEventObserver = new Observer<Object>() {
            @Override
            public void onSubscribe(Disposable d) {
            }

            @Override
            public void onNext(Object value) {
                if (value instanceof ThreadEvent) {
                    ThreadEvent event = (ThreadEvent) value;
                    ((TextView) getView().findViewById(R.id.TextView)).setText(event.message);
                    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onComplete() {
            }
        };

        }

参考サイト様

実装はこちらを参考にさせていただきました。
GitHub - nuuneoi/RxEventBus: A code example of the implementation of RxAndroid & RxJava as an EventBus on Android

RxJavaでイベントバスの機能を実装する考え方はこちらを参考にさせていただきました。
OttoからRxJavaへの移行ガイド - Qiita
RxJava as event bus, the right way – Dionysis’ Lorentzos blog

RxJavaに3日で入門し、Androidアプリのリスト操作、非同期処理、変更通知の課題を解決した話 - Qiita


以上です。