Schedulers for network requests in RxSwift Schedulers for network requests in RxSwift multithreading multithreading

Schedulers for network requests in RxSwift


Normally, i.e. if you do not specify any schedulers, Rx is synchronous.

The rest really depends on your use case. Four instance, all UI manipulations must happen on main thread scheduler.

Background work, including network requests, should run on background schedulers. Which ones - depends on priority and preference for concurrent/serial execution.

.subscribeOn() defines where the work is being done and .observeOn() defines where the results of it are handled.

So the answer to your specific questions: in case of a network call which results will be reflected in UI, you must subscribe on background scheduler and observe on main.

You can declare schedulers like that (just an example):

static let main = MainScheduler.instancestatic let concurrentMain = ConcurrentMainScheduler.instancestatic let serialBackground = SerialDispatchQueueScheduler.init(qos: .background)static let concurrentBackground = ConcurrentDispatchQueueScheduler.init(qos: .background)static let serialUtility = SerialDispatchQueueScheduler.init(qos: .utility)static let concurrentUtility = ConcurrentDispatchQueueScheduler.init(qos: .utility)static let serialUser = SerialDispatchQueueScheduler.init(qos: .userInitiated)static let concurrentUser = ConcurrentDispatchQueueScheduler.init(qos: .userInitiated)static let serialInteractive = SerialDispatchQueueScheduler.init(qos: .userInteractive)static let concurrentInteractive = ConcurrentDispatchQueueScheduler.init(qos: .userInteractive)

P.S. Some 3rd-party libraries may provide observables that are pre-configured to execute on a background scheduler. In that case explicitly calling .subscribeOn() is not necessary. But you need to know for sure whether this is the case.

And a recap:

  • normally, should I explicitly switch to a background thread when performing network requests?. - yes, unless a library does it for you

  • Should I, in every API request, explicitly change to background and then changes back to Main only when necessary? - yes

  • If so, what would be best way? [...] subscribe on background and observe on Main


You are right. Of course the actual network request, and waiting for and assembling the response, is all done on a background thread. What happens after that depends on the network layer you are using.

For example, if you are using URLSession, the response already comes back on a background thread so calling observeOn to do anything other than come back to the main thread is unnecessary and a reduction of performance. In other words, in answer to your question you don't need to change to a background thread on every request because it's done for you.

I see in the article that the author was talking in the context of Alamofire which explicitly responds on the main thread. So if you are using Alamofire, or some other networking layer that responds on the main thread, you should consider switching to a background thread if the processing of the response is expensive. If all you are doing is creating an object from the resulting dictionary and pushing it to a view the switch in context is probably overkill and could actually degrade performance considering you have already had to suffer through a context switch once.

I feel it's also important to note that calling subscribeOn is absolutely pointless for either network layer. That will only change the thread that the request is made on, not the background thread that waits for the response, nor the thread that the response returns on. The networking layer will decide what thread it uses to push the data out and subscribeOn can't change it. The best you can do is use observeOn to reroute the data flow to a different thread after the response. The subscribeOn operator is for synchronous operations, not network requests.