RxJava which operator to use - android

Is there any operator in RxJava to jump to the fetchAllParams(it) function if the filter operator returns false
That is, if UserAvailable.NOT_DETERMINED, I make a delay of 5 seconds and resend the same request, but if UserAvailable.DETERMINED, then the filter statement returns false and nothing happens.
fun checkUserAvailability(): Single<UserAvailable> = repository.serviceAvailable
.flatMap { fetchAllParams(it) }
.filter { it == UserAvailable.NOT_DETERMINED }
.delay(5, TimeUnit.SECONDS)
.flatMapSingle {
checkUserAvailability()
}
I also tried this option. How to put a delay just before the call to checkUserAvailability(), and not before flatMap
fun checkUserAvailability(): Single<UserAvailable> = repository.serviceAvailable
.flatMap { fetchAllParams(it) }
.flatMap {
if (it != UserAvailable.NOT_DETERMINED) {
Single.just(it)
} else {
checkUserAvailability()
}
}

Related

RxJava retryWhen with updated value + concurrency

I'd like to verify two things:
if the way I use retryWhen is correct or not. Basically, when an exception is caught, I want to get an updated value and rerun the sequence.
if another function also needs value, how to make it waits for updateValue to complete in the first instance? I've played with .share() and RxReplayingShare but I'm not sure how to use those properly.
val value = 0
#Test
fun test() {
executeFunction()
.retryWhen { errors -> errors.flatMap { error ->
if (error is WrongValue) {
updateValue()
.doOnSuccess { value = it }
.toObservable()
} else {
Observable.error(error)
}
}
}
}
fun executeFunction(): Single<Int> =
if (value == 0) {
Single.error(WrongValue())
} else {
Single.just(value)
}
fun updateValue(): Single<Int> = Single.just(1)

Wanted to fetch api after getting true value from observable emitter in RxJava

I am working on RxJava. I have created a random boolean stream of true and false values for observable class.
The observable class should be get repeated after a random duration of x seconds (between 10 and 90 seconds). After each true value, I need to call API and update the UI.
I have written the following code to generate random boolean values and pass them through observable. But how to repeat observable after every x seconds?
val r = Random
val apiResultStream = Observable.create(object : Observable.OnSubscribe<Boolean> {
override fun call(subscriber: Subscriber<in Boolean>) {
// emit true or false
subscriber.onNext(r.nextBoolean())
}
}).repeat(10)
apiResultStream
.subscribe { result ->
if (result === true) {
Log.v("ABC",""+result);
callAPI()
} else {
//callFailureApi()
Log.v("ABC",""+result);
}
}
I guess Observable.interval(30, TimeUnit.SECONDS) is what you need:
Observable.interval(30, TimeUnit.SECONDS) //also can specify scheduler
.flatMap { apiResultStream }
.subscribe { result ->
if (result === true) {
Log.v("ABC",""+result);
callAPI()
} else {
//callFailureApi()
Log.v("ABC",""+result);
}
}

Type mismatch returning an observable with fromCallable

The following code does not compile:
override fun storeConnections(connections: List<Connection>): Observable<List<Connection>> =
Observable.fromCallable<List<Connection>> {
appDao.storeConnections(connections.map {
mapper.toDb(it)})
}
The line with appDao.storeConnections indicates the following error:
Required List!
Found Unit
The storeConnections is done using Room:
#Dao
interface RoomDao {
#Insert(onConflict = REPLACE)
fun storeConnections(linkedInConnection: List<LinkedInConnectionEntity>)
}
The storeConnections is called from my rx stream:
val startPositions = BehaviorSubject.createDefault(0)
startPositions.flatMap { startPos -> App.context.repository.getConnections(startPos) }
.flatMap { connections -> Observable.fromCallable(App.context.repository.storeConnections(connections)) }
.doOnNext { ind -> startPositions.onNext(ind + 1) }
.subscribe({ ind -> println("Index $ind") })
How do I properly implement this fromCallable?
Given your reply to your question:
storeConnections is returning nothing. But I need to wrap it in an observable in order to push it down the stream. So maybe my question is how to wrap an API call with an Observable when that api call returns nothing.
I will answer how you can wrap it in an observable in order to push it down the stream:
.flatMap {
connections ->
App.context.repository.storeConnections(connections)
.andThen(Observable.just(connections))
}
Given that storeConnections returns a Completable:
override fun storeConnections(connections: List<Connection>): Completable =
Completable.fromAction {
appDao.storeConnections(connections.map { mapper.toDb(it) } )
}
}
If storeConnections returns "nothing", you could simply move the Completable.fromAction to your stream:
.flatMap {
connections ->
Completable.fromAction { App.context.repository.storeConnections(connections) }
.andThen(Observable.just(connections))
}
The key to getting it to work is using this:
return#fromCallable connections
So this is the corrected code:
override fun storeConnections(connections: List<Connection>): Observable<List<Connection>> =
Observable.fromCallable<List<Connection>> {
appDao.storeConnections(connections.map {
mapper.toDb(it)
})
return#fromCallable connections
}
And the rx stream that calls it:
val startPositions = BehaviorSubject.createDefault(0)
startPositions.flatMap { startPos -> App.context.repository.getConnections(startPos) }
.flatMap {
connections -> App.context.repository.storeConnections(connections)
}
.doOnNext {
connections -> startPositions.onNext(startPos++)
}
.subscribe({ ind -> println("Index $ind") })

RXKotlin Break Inside doOnNext and Call Another Function

i am using rx kotlin newly and didn't understand all of it yet. I am trying to loop over a list of queries, and execute them one by one. in this list i have a special string that once reached, i want to break the loop and perform another function
how can i do this in the below example?
fun runQueries() {
Observable.fromIterable(queriesTemp)
.subscribeOn(Schedulers.computation())
.doOnNext { query ->
if (query.contains("COMPLETION OF SDF QUERIES")) {
if (loginStatus == StaticVariables.FT_CASE_NEW_LOGIN) {
tasksQueriesTemp = arrayOfNulls(queries.size - queries.indexOf(query))
System.arraycopy(queries, queries.indexOf(query), tasksQueriesTemp, 0, tasksQueriesTemp!!.size)
}
// break the loop here
runOtherQueries()
break
}
if (!TextUtils.isEmpty(query)) {
mDatabase.execSQL(query, false, "")
}
action(tasksQueriesTemp!!.indexOf(query))
}
.doOnComplete { executeOtherUpdates(tasksQueriesTemp) }
.observeOn(AndroidSchedulers.mainThread())
.subscribe()
}
fun runOtherQueries() {
}
Factor out the part you want to break on from the doOnNext use takeWhile:
val broken = AtomicBoolean();
Observable.fromIterable(queriesTemp)
.subscribeOn(Schedulers.computation())
.takeWhile { query ->
if (query.contains("COMPLETION OF SDF QUERIES")) {
if (loginStatus == StaticVariables.FT_CASE_NEW_LOGIN) {
tasksQueriesTemp = arrayOfNulls(queries.size -
queries.indexOf(query))
System.arraycopy(queries, queries.indexOf(query),
tasksQueriesTemp, 0, tasksQueriesTemp!!.size)
}
// break the loop here
runOtherQueries()
broken.set(true)
return#takeWhile false // whatever the Kotlin syntax is for local returns
}
return#takeWhile true
}
.doOnNext { query ->
if (!TextUtils.isEmpty(query)) {
mDatabase.execSQL(query, false, "")
}
action(tasksQueriesTemp!!.indexOf(query))
}
.doOnComplete {
// if you don't want to execute the other updates if the code
// in takeWhile has "broken out of the loop"
if (!broken.get())
executeOtherUpdates(tasksQueriesTemp)
}
.observeOn(AndroidSchedulers.mainThread())
.subscribe()

OnComplete never called with toSortedList() and groupBy()

I'm currently using the Android-ReactiveLocation Library (Github). The LastKnownLocationObservable (Code) is working as intended. I'm using a flatMap to fetch nearby stations from a db and (because of realm) I'm creating a model from the data. So I have a list of items and I'm creating the new Observable in flatMap with Observable.from(data).
Then I want to sort the locations, filter them and group them.
.toSortedList()
.flatMap { Observable.from(it) }
.filter { it.distance <= (maxDistance.toDouble() * 1000) }
.groupBy { //Group the stations in categories
if (it.distance <= maxDistance && it.favorite) {
"nearbyFavorite"
} else if (it.favorite) {
"outOfReachFavorite"
} else {
"nearby"
}
}
However the onComplete is never called when I subscribe to the Observable. The Observable just stalls at toSortedList().
The Subscribe:
.subscribe(object: Subscriber<GroupedObservable<String, NearbyLocationItem>>() {
override fun onNext(p0: GroupedObservable<String, NearbyLocationItem>?) {
val locationItems = ArrayList<NearbyLocationItem>()
p0.subscribe { loc ->
locationItems.add(loc)
}
locations.put(p0.key, locationItems)
}
override fun onCompleted() {
Log.d(javaClass.simpleName, "Never called")
}
override fun onError(p0: Throwable?) {
}
}

Categories

Resources