first and single operator
According to the javadoc, first turns an observable into one that only returns 1 element and then terminates.
There's a similar operator called single. The difference is that the latter expects the source observable to only emit 1 item:
So, use first when you don't care how many items the source observable will emit. Otherwise use single.
When abstractions leakHowever, they behave different when you add doOnCompleted, doOnTerminate and doAfterTerminate to the mix. These operators allow you to do some side effects after the last item has been emitted.
The following code will print "onCompleted called":
Observable.just(1) .doOnCompleted(() -> System.out.println("onCompleted called") ) .single() .subscribe()
The next code won't:
Observable.just(1) .doOnCompleted(() -> System.out.println("onCompleted called") ) .first() .subscribe()
The next example will:
Observable.just(1) .first() .doOnCompleted(() -> System.out.println("onCompleted called") ) .subscribe()
So, you will get different behavior depending on where you put doOnCompleted and if you use single or first.
The reason why first behaves unexpectedly is because it unsubscribes from the source observable ones it receives the first element. As a consequence the source observable never has the opportunity to signal completion. As a result, an upstream doOnCompleted handler is never called while a downstream doOnCompleted handler is.
By contrast, single will wait until it receives the completion signal from the source observable allowing upstream doOnCompleted handlers to be called.