Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is passing Schedulers around best practice, a last resort or something in between? #3915

Closed
DavidMihola opened this issue May 6, 2016 · 6 comments
Labels

Comments

@DavidMihola
Copy link

This question is a follow-up to @artem-zinnatullin's comment to my question from yesterday.

For years now I've been using the static methods like Schedulers.io() and AndroidSchedulers.mainThread() to move my Observables around. Since I've started to write more tests I've also been trying to mostly move all subscribeOns and observeOns as far "to the ends" as possible: subscribeOn immediately after the Observables I get from Retrofit and observeOn immediately before any View related stuff.

This kept all the intermediate layers Scheduler agnostic and worked quite well except for two points:

  • All time sensitive operators use computation() by default - this is a problem for testing where I would like to use TestScheduler to be able to use "virtual time".
  • replay() seems to replay on the main thread by default - this just cost me three hours, because other parts of the app relied on a replayed Observable to also be on io().

So, both cases could be solved by putting a few subscribeOns in several places of my code, and passing Schedulers explicitly to interval(), etc.

In these cases, especially with regards to testing, is it best practice to mostly pass Schedulers around explicitly or is that seen as a last resort to be used when the default Schedulers fail or are inappropriate?

As always, thanks for any advice!

@artem-zinnatullin
Copy link
Contributor

Can't say that it's "best practice" or something, but in order to reduce amount of boilerplate ceremonies and number of parameters in the constructor we follow next practice:

class SomeViewModel { // Presenter/whatever, you got it.

  @Inject @TimeScheduler
  Scheduler timeScheduler;

  @Inject @IoScheduler
  Scheduler ioScheduler;

  SomeViewModel(ObjectGraph graph) {
    graph.inject(this);
  }
}

Then in tests we just pass test implementation of the ObjectGraph that injects required schedulers like TestScheduler/Schedulers.immediate()/Schedulers.trampoline() to execute tests synchronously.

// Finally got rid of using Schedulers hook in our test suite today because we saw some shared state problems, really happy about it.


Also in case if you're interested, looks like that we've finally found a good solution for dealing with ViewModel/Presenter -> View reactive interaction that solves 3 main problems:

  1. MainThread should be part of View implementation.
  2. Action posted to MainThread should be part of Subscription (to unsubscribe).
  3. Backpressure occurred on MainThread should be detected and handled on ViewModel/Presenter layer.

Nothing published yet because (I need some free time + try it in real life project), but you can track discussion/progress here.

@akarnokd
Copy link
Member

I'm closing this issue due to inactivity. If you have further input on the issue, don't hesitate to reopen this issue or post a new one.

@artem-zinnatullin
Copy link
Contributor

@DavidMihola as promised, finished solution regarding passing around RxAndroid's main thread scheduler: RxUi, feedback is welcomed!

@westonal
Copy link

@artem-zinnatullin How do you achieve @Inject @IoScheduler where does IoScheduler come from or how is it defined?

@westonal
Copy link

@artem-zinnatullin Nevermind, custom Qualifiers I assume http://docs.oracle.com/javaee/7/api/javax/inject/Qualifier.html

@artem-zinnatullin
Copy link
Contributor

artem-zinnatullin commented Jun 12, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants