Office Hours — Today, December 15

Thursday, December 13

Dec 15
3:55 PM
Mark M.
has entered the room
Mark M.
turned on guest access
4:00 PM
Aaron
has entered the room
Mark M.
hello, Aaron!
how can I help you today?
Aaron
hello, Mark
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
#1-3 are the priorities if there is not time for all
here they are:
View paste (6 more lines)
1. LiveDataReactiveStreams says it subscribes/unsubscribes whenever the LiveData becomes active/inactive (aka has at least one observer (?)), so correct me if I am wrong, but, when using LiveDataReactiveStreams to switch from Rx to LiveData in the ViewModel, wouldn't that mean that any ongoing stream processing/subscriptions would be halted on config changes? Whereas in my other scenario (using setValue() in the Rx subscriber to create a MutableLiveData and manually disposing the subscription in onCleared()), stream processing would _continue_ through config changes and only be halted whenever onCleared() happens, i.e., when the activity/fragment is not going to be recreated. Right? So that would be a fairly substantial difference between those two scenarios, beyond what we identified last time re: LiveDataReactiveStreams 1) eliminating the MutableLiveData and 2) automatically unsubscribing.

2. On the topic of unsubscribing, I want to push back on your previous statement that "you need to call dispose() on [all Rx observables] at some point, when you are done ... that does not happen automatically for any Rx type". According to http://reactivex.io/documentation/contract.html, "Whe
...
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
that would depend a bit on the Observable in question -- most hot observables I would expect to be unaffected
Aaron
hm, good point
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
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
there is no harm in re-disposing a disposed Disposable
Aaron
roger that
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
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:
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
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
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
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
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
hmm
OK
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
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
it is your job to catch any exceptions
4:20 PM
Mark M.
if you want the UI layer to know about the problem, that is your job as well
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>)
the phrasing that you cited says that Thingy needs to contain both positive and negative results
alternatively, you can have a separate LiveData for problems
so you have LiveData<Thingy> for the "real" result and a LiveData<Problem> for when things go wrong
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
whether you use events or not depends a bit on how you wish to inform the user about problems
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
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
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
I suspect that question is nonsensical
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
an Rx error handler lambda is a controlled and relatively centralized thing
4:30 PM
Mark M.
throwing an exception from an Rx error handler tosses that out the window
(and frankly I don't really know what happens if you try that with some sort of RuntimeException)
Aaron
I see
so, what you are saying is,
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
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
nice, ok
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
it makes me a little nervous because I don't understand why they called it switchMap instead of flatMap
but as far as I can tell, it's analogous to flatMap and not Rx switchMap
Mark M.
¯\_(ツ)_/¯
4:35 PM
Aaron
indeed
alright - thanks again and enjoy the rest of the weekend
Mark M.
you too!
Aaron
has left the room
5:00 PM
Mark M.
turned off guest access

Thursday, December 13

 

Office Hours

People in this transcript

  • Aaron
  • Mark Murphy