How to return an Observable from a Completable? I’...
# android
m
How to return an Observable from a Completable? I’ve tried this but I couldn’t get mObservableData on subscription
Copy code
return data.flatMapCompletable{...}.andThen(mObservableData)
g
What do you mean “How to return an Observable from a Completable”?
Something like that?
.andThen { someLazyObservable }
m
I mean after* not from .. sorry
g
andThen
has different overloaded versions including one for Observable, eager and lazy
m
I mean this one
andThen(Observable)
g
What is your problem with this?
andThen allows to chain completable with any other RxJava primitive, what exactly doesn’t work?
a
Copy code
Observable.just(1, 2, 3)
    .flatMapCompletable {
        Completable.complete()
    }
    .andThen(Observable.just(3, 4, 6))
    .test()
    .assertValues(3, 4, 6)
worked for me
g
of course, It should work, never see problem with
andThen
m
Copy code
fun getUsers(): Observable<User> {
        return getUserInfo()
                .map { ... }
                .flatMapCompletable { it.saveToRealm() }
                .andThen (usersFromRealm())
    }
I receive data from API so I want to save it to db first then return an Observable
usersFromRealm()
a
what type is
saveToRealm()
?
m
It’s a Completable
a
are you sure
getUserInfo
emitted anything?
m
Yes, data are saved in db!
a
does
saveToRealm
signal
onSuccess
when that happens? 🙂
two things I'd try: 1. replace
it.saveToRealm()
with
Completable.complete()
2. replace
usersFromRealm()
with
Observable.just(User(/*...*/))
m
yes it signals
onComplete
saveToRealm()
:
Copy code
return userInfoObservable.flatMapCompletable { Completable.fromCallable { it.save() }
a
I mean in the implementation of
getUsers
I'd change that, just to check if it's correct
m
Actually I’ve tried the second one
Observable.just(User())
and got nothing
a
maybe try 1. and 2. at the same time
that should work without any issue I suppose
m
I did try both now .. nothing in return
There are no issues with the ViewModel ..
a
how do you subscribe to it?
what if you create a unit test and invoke
getUsers().test().assertValue(User())
(with 1. and 2.)?
m
Copy code
mGetUsersUseCase.execute()
                .doOnNext {
                    mUserLiveData.value = it
                }
                .doOnCompleteLog()
                .autoDisposable(this)
                .subscribeWith(RxLogSubscriber(UserViewModel::class.java.simpleName))
doOnCompleteLog
is just an extension
Ok I’ll do it
a
BTW, isn't
LiveDataReactiveStreams.fromPublisher
the same as what you are trying to achieve here with
liveData.value = it
and
autoDisposable
?
g
btw why do you request the same data from realm? Maybe just do something like:
userInfoObservable.flatMap { it.apply { save() } }
I just not sure how realm works, maybe there is no data in databaase yet, or some cache or any other issue. Probably you could reproduce your problem on some self-contained sample
m
I tried
getUsers().test().assertValue(User())
and got an NPE
LiveDataReactiveStreams.fromPublisher
is a good practice? Because I heard it’s not
a
about npe, you probably need to mock
getUserInfo
to return some observable, but that's a guess
about
fromPublisher
I'd be interested to hear about any problems with it, but I don't know about any
m
@gildor I want to return a
Completable
that’s why I’m using
flatMapCompletable
g
But you return observable with data after completable, that's my point, you save something to do and then request it immediately
m
it.save()
doesn’t return an observable
Actually, that’s what I wanted; To save data to Realm from API and return an observable from the database that’s why I do request it immediately. Is there another option?
g
Check my code snippet. It returns it and calls save as side effect
Another option save, but do not request data from db again, but just return it
m
So I understand that data returned will be from the API not from Realm. Is that what you’re saying?
g
I suppose you problem is that observable from db do not return to you just inserted data for some reason
Yes
At least for this particular case, when save to db is just side effect
m
I was doing this before!
So, I can’t just listen on the db with an Observable and once data are saved .. I get it?
g
I don't know how Realm and Realm Rx API works, but I can imagine API when you return observable that emits only new items (updates of items) But return data immediately rather than request it from db looks as more efficient and fast way
✔️ 1
m
Thank you guys for help! 🙂 @gildor @arekolek
👍 1
d
Sorry for bumping, but I had simillar problem few days ago. You can chain multiple calls with zip()
g
Zip can be used to chain request, but just for chaining there are more suitable operators, most common of them is flatMap and andThen for Completable
Also, zip is not available on Completable
d
Well.. you can go with Single.zip and then flatMapCompletable
andThen requires another dependency
I tend to avoid that as I'm not really sure about reuseability to other RxExtensions
g
It's not true. andThen is not another dependency, this is standard method of Completable in RxJava1 and RxJava2
Could you please provide an example of Single.zip for chaining, I really not sure that this is the best solution for pure chaining but maybe you could show me a good use case
d
yes sure, just a sec
Copy code
override fun validateAdminWithCredentials(username: String, password: String): Single<Authenticator> {
        return Single.zip(checkIfPopulated(), findAdministratorInDatabase(username, password), BiFunction<Boolean, Boolean, Pair<Boolean, Boolean>>
        { t1, t2 -> Pair(t1, t2) })
                .flatMap { pair ->
                    val returnValue = if (pair.first) {
                        Single.just(Pair(pair.second, false))
                    } else {
                        Single.fromCallable { local.adminDao().insert(createDefaultAdmin()) }.map { Pair(pair.second, true) }
                    }
                    returnValue
                }
                .map { Authenticator(it.first, it.second) }.subscribeOn(<http://Schedulers.io|Schedulers.io>())

    }
what this does is this: checks if admin table is populated: FALSE create default administrator and notify user about it TRUE validate administrator: TRUE notify user about success FALSE notify user about failure OnERROR trigger onError for fail I/O communication
@gildor
I stand corrected for andThen! Thanks 🙂
Is andThen executed after Completable emits complete only or is it executed after emitter.complete or emitter.error?