i try to get an array of flowable get executed in parallel with FlowableFromArray
and emit the FlowableFromArray when all flowables are done.
But I'm missing the method to emit on last/latest.
I could only manage to make it work to emit onNext #see below
val results = FlowableFromArray(flowableArray).parallel()
.runOn(Schedulers.io())
.sequential()
.zipWith(r, BiFunction { t1: Flowable<String>, t2: Int
->
t1
.subscribeOn(Schedulers.io())
.map { i -> parseYoutubeTrack(i) }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { next -> TLog.i(TAG, "_NEXT_ ${next.videoId}") }
})
.subscribe()
Related
For a nested observable, the nested observable's onComplete is not called when the same code is written in Kotlin.
The nested observable onNext gets called, but does not call onComplete and the call gets completed.
There is no exception thrown at either of the .subscribe calls.
Is there any equivalent to Coroutine code
val listItem = async {
...
}
val data = listItem.await()
output sequence for the following bit of code is:
// observable 1 completed
// observable 2 completed
getListObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidScheduler.mainThread())
.subscribe(
{
listItem ->
getListItemParams(listItem.id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidScheduler.mainThread())
.subscribe(
{ paramList: List<BaseObservable?> ->
},
{ throwable: Throwable ->
},
{
// observable 2 completed
},
Disposable? ->
}
)
},
throwable: Throwable? ->
},
{
// observable 1 completed
},
Disposable? ->
}
)
I have tried wrapping the nested called in a CompositeDisposable, but with same results.
update:
getListItemParams(listItem.id) is a call to Room db query which returns an Onservable to subscribe to.
#Query("SELECT * FROM my_table WHERE id = :id")
fun getListItemParams(id:Int): Observable<List<DataPoint>>
I use RXAndroidBle to connect to Bluetooth devices. I use establishConnection to get the connection observable and want to convert this Observable to an Completable. This code works and the completable completes as expected:
connectionObservable
.observeOn(AndroidSchedulers.mainThread())
.doOnNext {
...
startReadingData()
}
.doOnError { ... }
.take(1)
.ignoreElements()
whereas this never completes:
connectionObservable
.observeOn(AndroidSchedulers.mainThread())
.doOnNext {
...
startReadingData()
}
.doOnError { ... }
.flatMap { Observable.just(it) }
.ignoreElements() // flatMapCompletable { Completable.complete() } doesn't work either
So I'm purly asking out of interest, why does flatMap with Observable.just() not work, as Obsrevable.just() also completes immediately?
Problem
Never completes:
connectionObservable
.observeOn(AndroidSchedulers.mainThread())
.doOnNext {
...
startReadingData()
}
.doOnError { ... }
.flatMap { Observable.just(it) }
.ignoreElements() // flatMapCompletable { Completable.complete() } doesn't work either
This is actually quite simple. The connectionObservable is probably infinite. It will call onNext, but not onComplete. The downstream operators receive the onNext emit and process it accordingly. The flatMap operator only completes, when the upstream and the inner-stream emits onComplete. The inner-stream of flatMap completes, but not the source-observable. Therefore you do not get a terminal messages, ever.
Completes
connectionObservable
.observeOn(AndroidSchedulers.mainThread())
.doOnNext {
...
startReadingData()
}
.doOnError { ... }
.take(1)
.ignoreElements()
This stream completes, because there is a terminal operator. In this case you have a take(1). What does the Take-Operator do? It will wait for an onNext emit from source and transforms it to onNext(message) and onComplete(). You could add the flatMap with Observable.just as inner-stream below the take-Operator and it would still complete.
Take-Operator Impl
#Override
public void onNext(T t) {
if (!done && remaining-- > 0) {
boolean stop = remaining == 0;
downstream.onNext(t);
if (stop) {
onComplete();
}
}
}
The implementation of the Take-Operator in RxJava2 looks like this. It is clear, that a upstream onNext will result in a onNext and possibly a onComplete (downstream).
I have a list of Items I want to map and then insert into a Room table:
Room
#Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg projectLocal: ProjectLocal): Completable
The FIRST approach to save data:
Observable.fromIterable(remoteProjects)
.map { project ->
...
mProjectMapper.mapRemoteToLocal(project)
}
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe {
mProjectRepository.saveProject(it)
}
As you may see I'm observing on -> main thread and subscribing on -> io
The Second approach to save data:
remoteProjects.forEach { remote ->
...
val project = mProjectMapper.mapRemoteToLocal(remote)
mProjectRepository.saveProject(project)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe()
}
Which one makes more sense? Is there any better way to save all this data inside a Room database using RxJava?
I think this is what #Mwasz means:
Observable.fromIterable(remoteProjects)
.map { project ->
mProjectMapper.mapRemoteToLocal(project)
}
.toList()
.flatMapCompletable {
mProjectRepository.saveProject(it)
.subscribeOn(Schedulers.io())
}
.subscribe()
You could also use reduce or collect instead of toList but toList() is the simplest.
I have the method below:
private fun bindUploadPhotos(uploadPhotoCommands: List<UploadPhotoCommand>): Disposable {
return Observable.fromIterable(uploadPhotoCommands)
.concatMapSingle { param ->
requestUploadPhoto.getSingle(param)
}
.doFinally {
onAllPhotosUploaded()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
onPhotoUploaded()
}
}
I upload photos sequentially. I expect doFinally to execute after all photos are uploaded successfully. However, it executes immediately.
I am not a RxJava2 master, so I gladly take your different approaches to achieve my purpose.
onComplete called when all your photos uploaded. so call onAllPhotosUploaded there
private fun bindUploadPhotos(uploadPhotoCommands: List<UploadPhotoCommand>): Disposable {
return Observable.fromIterable(uploadPhotoCommands)
.flatMapSingle { param ->
requestUploadPhoto.getSingle(param)
}.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({onPhotoUploaded},{},{onAllPhotosUploaded()})
}
I am searching for a doOn... callback for a ConnectableObservable that is invoked when every observer terminates
val gatewayItems = viewModel.getGatewayItems(gateways!!)
.observeOn(Schedulers.io())
.take(1)
.publish()
.autoConnect(2)
gatewayItems.subscribe { sharedGateways -> sharedGatewaysAdapter.submitList(sharedGateways) }
gatewayItems.subscribe { sharedGateways -> privateGatewaysAdapter.submitList(privateGateways) }
I would like to get a callback to my multicasted hot observable when both of my observers signal a terminal event
I have tried to put doOnTerminate and doOnComplete operators on my parent multicasted observable but, it seems that these callbacks are invoked 2 times (one for each observer)
val gatewayItems = viewModel.getGatewayItems(gateways!!)
.observeOn(Schedulers.io())
.take(1)
.doOnComplete { ... }
.doOnTerminate { ... }
.publish()
.autoConnect(2)
Both .doOnComplete and .doOnTerminate work for me.
Edit: the chances are you might be attaching the do... operators in incorrect order. For example, neither of these doOnComplete will work:
val gatewayItems = viewModel.getGatewayItems(gateways!!)
.observeOn(Schedulers.io())
.doOnComplete { ... }
.take(1)
.publish()
.autoConnect(2)
.doOnComplete { ... }