j2emanue
j2emanue

Reputation: 62519

RxJava android - does observer block

Given this simple Observer and subscriber combo which simply observes a file IO and then updates in the subscriber based on the value:

Observable.just(preferences.getBoolean(C"vibrate", false))
            .subscribeOn(Schedulers.io())//observe on new thread
            .observeOn(AndroidSchedulers.mainThread()) //subscribe(listen) on main thread
            .subscribe(new Action1<Boolean>() {
                @Override
                public void call(Boolean shouldVibrate) {
                    if (shouldVibrate)
                        Toast.makeText(context,"i should vibrate now",Toast.SHORT).show();
                }

            });

My question is, does the observer block until write is complete ? Even though i specify another thread (IO thread) does this observer still block once called by the subscriber ?

Upvotes: 1

Views: 760

Answers (1)

dwursteisen
dwursteisen

Reputation: 11515

Your Observer won't block as your operation be done BEFORE you subscribe to your Observer (so, it will just emit your value)

Regarding your code (java 8 style for simplicity) :

Observable.just(preferences.getBoolean("vibrate", false))
        .subscribeOn(Schedulers.io())//observe on new thread
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(shouldVibrate) -> {
                if (shouldVibrate) {
                    Toast.makeText(context,"i should vibrate now",Toast.SHORT).show();
                }
        });

You can extract the call as a variable preferences.getBoolean(C"vibrate", false) :

Boolean vibrate = preferences.getBoolean("vibrate", false);
Observable.just(vibrate)
        .subscribeOn(Schedulers.io())//observe on new thread
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(shouldVibrate) -> {
                if (shouldVibrate) {
                    Toast.makeText(context,"i should vibrate now",Toast.SHORT).show();
                }
        });

As you can see, the vibrate will be computed before and then the main thread will be blocked.

You should write a "lazy" call to your method using Observable.create method

Observable.create(sub -> {
              Boolean vibrate = preferences.getBoolean("vibrate", false);
              sub.onNext(vibrate);
              sub.onCompleted();

         })
        .subscribeOn(Schedulers.io())//observe on new thread
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(shouldVibrate) -> {
                if (shouldVibrate) {
                    Toast.makeText(context,"i should vibrate now",Toast.SHORT).show();
                }
        });

With this code, the Boolean vibrate = preferences.getBoolean("vibrate", false); will be called only when you'll subscribe to your Observer.

(regarding to your if, in your subscriber, you can change it with a filter)

        Observable.create(sub -> {
              Boolean vibrate = preferences.getBoolean("vibrate", false);
              sub.onNext(vibrate);
              sub.onCompleted();

         })
        .filter((value) -> value)
        .subscribeOn(Schedulers.io())//observe on new thread
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(shouldVibrate) -> {
                    Toast.makeText(context,"i should vibrate now",Toast.SHORT).show();
        });

Upvotes: 1

Related Questions