Dec 15 | 3:55 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Dec 15 | 4:00 PM |
Aaron | has entered the room |
Mark M. |
hello, Aaron!
|
Mark M. |
how can I help you today?
|
Aaron |
hello, Mark
|
Aaron |
I think I understand LiveDataReactiveStreams better now, I was confused due to a combination of smaller misunderstandings such as when onCleared() happens and what disposing actually entails. So, I have some new/updated questions
|
Aaron |
#1-3 are the priorities if there is not time for all
|
Aaron |
here they are:
|
Aaron |
View paste
(6 more lines)
|
Dec 15 | 4:05 PM |
Mark M. |
with regards to 1, "wouldn't that mean that any ongoing stream processing/subscriptions would be halted on config changes?" -- at most, only if your Rx chain stops its work if there is no active subscription
|
Mark M. |
that would depend a bit on the Observable in question -- most hot observables I would expect to be unaffected
|
Aaron |
hm, good point
|
Aaron |
but for a cold observable, everything I said in (1) would hold true?
|
Mark M. |
possibly -- I do not claim to know all of the ins and outs of the behavior of different types of Rx observables
|
Mark M. |
IOW, run tests
|
Aaron |
OK
|
Mark M. |
2. "but strictly speaking, doesn't this mean that Observables _do_ automatically dispose themselves?" -- yes, but since the Rx work is happening asynchronously with respect to things like lifecycle methods, always dispose them yourself
|
Mark M. |
there is no harm in re-disposing a disposed Disposable
|
Aaron |
roger that
|
Dec 15 | 4:10 PM |
Mark M. |
3. "I need to combineLatest() (instead of the zip() that we talked about previously) my Single Retrofit calls with an Observable coming out of Room" -- this feels like an architecture problem
|
Mark M. |
are you actually trying t observe Room changes with the Observable? or is this a one-time request and you could change your Room DAO to use a Single?
|
Aaron |
um, I think I need the Observable, the specific situation is this:
|
Aaron |
the Retrofit Single is getting a list of posts from Reddit; the Room Observable is emitting an array of post IDs that have already been clicked, and I am using combineLatest() to package that all up into one viewstate object so the UI knows which posts have been clicked, to display them appropriately
|
Aaron |
and so the Observable coming out of that is updated each time a new post is clicked and its ID is inserted into the Room DB
|
Aaron |
so I use combineLatest() so the UI is updated when either 1) the user refreshes, so the content is updated or 2) when the user clicks a post, so the post title is struck-through
|
Mark M. |
the only way that I can think of, off the top of my head, is to combineLatest() your Room Observable with a PublishSubject, so you have a stable combined Observable that your consumers can consume
|
Dec 15 | 4:15 PM |
Mark M. |
when you make a Retrofit call, your repository subscribes to the Single and in its subscribe handler updates the PublishSubject with the result
|
Mark M. |
it's possible there is a way just with Rx operators to achieve what you want, but my Rx-fu is weak
|
Aaron |
no worries, with regard to the PublishSubject, do you know off the top of my head which methods/operators I should look more closely at?
|
Mark M. |
none -- you just call onNext() when you get your Retrofit result
|
Aaron |
that is the solutoin I roughly identified, I am just having trouble figuring out the details
|
Aaron |
hmm
|
Aaron |
OK
|
Aaron |
have to think about that while looking at some actual code after the chat
|
Mark M. |
OK
|
Aaron |
sounds like it's not as difficult as I was thinking
|
Mark M. |
in terms of 4, when you subscribe() to an Rx type, you have to provide something to handle both positive results and errors, such as two lambda expressions
|
Mark M. |
and so if something goes "boom" anywhere in the Rx chain, the exception winds up in your onError handler
|
Aaron |
yes, right
|
Mark M. |
LiveData does not do this
|
Mark M. |
it is your job to catch any exceptions
|
Dec 15 | 4:20 PM |
Mark M. |
if you want the UI layer to know about the problem, that is your job as well
|
Mark M. |
for manual uses of LiveData, such as a MutableLiveData, the fact that you need to handle the exceptions becomes fairly obvious, as you can't somehow shove an Exception into a MutableLiveData as a separate thing from whatever it is really of (e.g., MutableLiveData<Thingy>)
|
Mark M. |
the phrasing that you cited says that Thingy needs to contain both positive and negative results
|
Mark M. |
alternatively, you can have a separate LiveData for problems
|
Mark M. |
so you have LiveData<Thingy> for the "real" result and a LiveData<Problem> for when things go wrong
|
Mark M. |
both would be held in your viewmodel, and your activity/fragment/whatever can observe each of them
|
Aaron |
it sounds like that's basically what I am doing already, as I described in (5)
|
Mark M. |
yes
|
Mark M. |
whether you use events or not depends a bit on how you wish to inform the user about problems
|
Mark M. |
if you are displaying them in a transient fashion (toast, dialog, snackbar, etc.), then LiveData<Event<Problem>> is the right answer
|
Aaron |
I was just getting tripped up with this part -> "as state", thought it meant something fancier than it apparently does
|
Aaron |
ok great, so in light of that let me revise question 5 slightly
|
Mark M. |
nah, that's just trying to come up with short memorable phrasing, I suspect
|
Aaron |
got it
|
Dec 15 | 4:25 PM |
Aaron |
this is going to be a bad question and I could probably figure it out by experimentation, but let me just ask while we're still here,
|
Mark M. |
the only bad questions are the ones written in Klingon or something else that I can't understand
|
Aaron |
if I try throwing Exceptions generated in the repository back to the caller, what is going to happen to them? I have some kind of vague idea of them propogating back to the ViewModel or Activity, but I have a poor understanding of Exceptions in general
|
Aaron |
I suspect that question is nonsensical
|
Aaron |
that's what I meant, by, can I get them back to the UI layer without the LiveData
|
Mark M. |
while that's not a bad question, what you're describing sounds like a really bad idea
|
Aaron |
but I think I'm mixing up like, the call stack vs. the layers of my app
|
Mark M. |
our objective with exceptions is to learn about problems and deal with them, ideally in a controlled and relatively centralized fashion
|
Mark M. |
an Rx error handler lambda is a controlled and relatively centralized thing
|
Dec 15 | 4:30 PM |
Mark M. |
throwing an exception from an Rx error handler tosses that out the window
|
Mark M. |
(and frankly I don't really know what happens if you try that with some sort of RuntimeException)
|
Aaron |
I see
|
Aaron |
so, what you are saying is,
|
Aaron |
don't re-throw Exceptions unless you are firmly in control of the call stack (is that the right term?) and you know exactly where they are going to end up
|
Mark M. |
yes
|
Mark M. |
and only re-throw exceptions if you really have no way to deal with them wherever you are
|
Aaron |
yeah, so I was thinking of it like, UI layer calls a method in the ViewModel that calls a method in the repository, and then I could re-throw the Exceptions and get them back to the UI layer, but that's not really true, because I actually have no idea what is calling what in-between those steps
|
Mark M. |
right
|
Aaron |
great, I think I get it
|
Aaron |
nice, ok
|
Aaron |
awesome, well that really clears up a lot, and that's all I have for now, so thanks
|
Mark M. |
you're welcome!
|
Aaron |
by the way, w/r/t one thing I previously asked, about LiveData switchMap vs. Rx switchMap, I looked into that a bit and as far as I can tell, LiveData switchMap is actually just an analogue of Rx flatMap
|
Aaron |
it makes me a little nervous because I don't understand why they called it switchMap instead of flatMap
|
Aaron |
but as far as I can tell, it's analogous to flatMap and not Rx switchMap
|
Mark M. |
¯\_(ツ)_/¯
|
Dec 15 | 4:35 PM |
Aaron |
indeed
|
Aaron |
alright - thanks again and enjoy the rest of the weekend
|
Mark M. |
you too!
|
Aaron | has left the room |
Dec 15 | 5:00 PM |
Mark M. | turned off guest access |