Office Hours — Today, December 11

Saturday, December 8

Dec 11
7:25 PM
Mark M.
has entered the room
Mark M.
turned on guest access
7:45 PM
Aaron
has entered the room
Mark M.
hello, Aaron!
how can I help you today?
Aaron
hello Mark, I have 3 questions today, here they are:
View paste (2 more lines)
1. In our last conversation I asked about the difference between creating a MutableLiveData viewstate in my repository vs. exposing an observable that gets converted to LiveData in the ViewModel with LiveDataReactiveStreams. If I understood your answer correctly, the difference is that LiveDataReactiveStreams unsubscribes from your observable when your LifecycleOwner is outside of onStart() - onStop() so that it doesn't do unnecessary stream processing when the UI can't receive updates. First, have I understood that correctly? Second, to follow on, if all I were using Rx for in my repository were `Single` Retrofit calls, as far as I can tell, LiveDataReactiveStreams would offer no additional advantage versus a MutableLiveData, since each subscription would end after each network call, anyway, and no redundant work would happen. (This isn't exactly my situation, actually, as you may see in question #3 but I would still like to confirm whether I am thinking about it right).

2. I have read things along the lines of, "LiveData has to represent errors as state." Can you explain what this means and briefly compare it to how errors are handled in Rx?

3. All that said, I've finished swit
...
Mark M.
"First, have I understood that correctly?" -- yes, though there is nothing stopping you from disposing of the Rx subscription yourself in onCleared() of the ViewModel
"if all I were using Rx for in my repository were `Single` Retrofit calls, as far as I can tell, LiveDataReactiveStreams would offer no additional advantage versus a MutableLiveData" -- if all you were using is Rx, LiveDataReactiveStreams probably doesn't exist in your app, as you would not be pulling in the LiveData stuff, and certainly not the LiveData/Rx bridge dependency
OK so far?
Aaron
for the second part, the question is, if all i were using _Rx for_ were the network calls - not implying that I am not also using LiveData
7:50 PM
Aaron
using Rx to construct the viewstate that gets wrapped in a LiveData to feed the UI
is the idea.
the key part of the question is about Singles as opposed to something like a Flowable where stream processing would be ongoing
since a Single completes the subscription after the first value is emitted, as far as I can tell, LiveDataReactiveStreams won't do much for you, if you are only using Singles, since you won't have any ongoing emissions
does that make sense?
Mark M.
well, not really
you use LiveData to get the reactive events to the UI layer, so it is lifecycle-aware
it does not matter whether there is zero, one, or ten million reactive events
nor does it matter whether the events are triggered by disk I/O, network I/O, Bluetooth I/O, or anything else
you don't have to use LiveDataReactiveStreams to pipe Rx data into LiveData
but similarly, there is nothing intrinsically wrong with doing so, even for Single
if the subscriber of the Single is not the UI layer (via a ViewModel), then LiveDataReactiveStreams has no meaning
so, for example, if the Single is being used by a service for a sync operation, there is no LiveData and no need for LiveDataReactiveStreams (or any other Rx -> LiveData pipeline)
7:55 PM
Mark M.
Rx makes a distinction between the numbers of events: Observable, Single, Completable, etc.
LiveData doesn't, in large part because it is really just a value holder with a callback mechanism
so, I think it is a mistake to say that there is no value in using LiveDataReactiveStreams with a Single
you don't have to use it, and I suspect in many cases you'll do something else anyway (e.g., your MutableLiveData), but it's not completely insane to use it, either
anything else on #1 before I move on to #2?
Aaron
hmm, something is still off with my understanding, I guess another way to state my question is this: before I included Rx at all, I was also constructing a MutableLiveData in my repository (the same thing I am doing with Rx now), the only difference was, I was doing it with MediatorLiveData and LiveData transformations instead of Rx. but in both cases I was construcitng the MutableLiveData in my repository and exposing it to the ViewModel, and subsequently the UI. so the point where I get confused is, there didn't seem to be any lifecycle issues before, and since the repository is exposing the exact same thing now, it seems like there shouldn't be lifecycle issues now, and if there aren't any, then I guess I don't really understand what LiveDataReactiveStreams does, then
Mark M.
well, it eliminates the MutableLiveData
8:00 PM
Mark M.
and it handles the unsubscribe operation for you, so your ViewModel does not have to worry about it
you chose to use MutableLiveData, which is a reasonable choice, but it is not a requirement of using Rx with LiveData
Aaron
(thinking and typing)
Mark M.
TimeMachine/RoomFTS, Diceware/Repository, Trips/RxLifecycle, Diceware/Pwned, and other samples in "Android's Architecture Components" shows how to use Rx with LiveData, generally without your own MutableLiveData
Aaron
so I understand the eliminating the MutableLiveData part, that makes total sense, but I don't think I fully grasp what the unsubscribe operation entails, then. I thought it was something like this: Rx chains only execute when there is a subscriber. so LiveDataReactiveStreams makes sure you don't do redundant background work when the UI can't receive updates, by taking away that subscriber when the UI cannot do so. so that was where I was bringing in the distinction between Single and Flowable, because my understanding was that a Flowable represents ongoing work where there is a continuous subscription, versus a Single where the subscription starts and then immediately ends after the single event
and no subscription = no need to unsubscribe
I just can't pin down the exact place where I am misunderstanding
8:05 PM
Mark M.
you certainly need to dispose() your Single subscription
every call to subscribe() on an Rx type returns a Disposable
you need to call dispose() on it at some point, when you are done
that does not happen automatically for any Rx type
Aaron
ok, well I certainly misunderstood that, I thought you only needed to dispose the subscription if you chose to hold onto the disposable
Mark M.
nope
now, I have been sloppy about that
Aaron
I see
Mark M.
one of the many Rx things that I will be cleaning up as part of the Great Book Rewrite
Aaron
tell you what, maybe if you could skip to question #3, some of this will be clarified in the process of working on that question
Mark M.
before I forget, if you want Lint to yell at you about Rx hiccups like this, check out rxlint: https://bitbucket.org/littlerobots/rxlint
Aaron
discussing in terms of concrete examples in my code will probably help
OK, thanks, I'll check it out
Mark M.
I think the standard is to use Schedulers.io() for network I/O, not Schedulers.computation(), though that's really your call
8:10 PM
Aaron
so I specified Schedulers.io() as part of my Retrofit builder call, as the default
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
what I am (attempting) to do there, is switch to the computation thread for the map call
should the map transformation stay on the io thread?
Mark M.
unless that map work will be *really* slow, the overhead of the thread switch isn't worth it IMHO
Aaron
since it is a data transformation and not really I/O anymore,
^ was my reasoning
OK, got it
Mark M.
if the data transformation is expensive (e.g., image processing), then that's reasonable
Aaron
understood
Mark M.
as you don't want to tie up the I/O thread, perhaps
I think you are the first developer that I have seen use Flowable -- the *vast* majority of RxJava work seems to be based on Observable more so than Flowable
to be clear, I mean "I have seen use Flowable directly" (versus toFlowable() calls en route to something else, such as via LiveDataReactiveStreams)
there's nothing particularly wrong with Flowable, but your choice is unusual, and it's the sort of choice that you'll want to be able to defend in an interview or code review
I would not have the repository expose LiveData -- I would have it expose Rx types and have the viewmodel do the LiveData work
Aaron
I see, some of the documentation I read about Rx1 vs Rx2 say that Flowable should be the default now unless you have a reason not to, as it handles backpressure automatically (not that this simple stuff is necessarily going to create backpressure), and since I did not have a particularly strong reason, that's why I used it
that info may be inaccurate
8:15 PM
Aaron
or perhaps, the work being simplistic enough that it's not going to create backpresure, *is* a good enough reason to use Observable
Mark M.
I'm more going by what I see in blog posts, Stack Overflow questions, presentations, and the like
Aaron
ok, I'll research it further
Mark M.
those would be my comments on that code, from a quick scan of the Rx bits
Aaron
hmm, yes, it seems like that advice is an oversimplification, this page is not so black and white on it
I'll read up on it
OK, thanks for that
Mark M.
there are probably teams out there that have standardized on Flowable, for various reasons
and, in terms of the app itself, there's probably nothing wrong with your use of it
Aaron
yeah, I hear what you are saying though
needs to be a more defensible choice, whatever it is
Mark M.
where if you lack a defense, take the default, which right now is Observable
8:20 PM
Aaron
in my defense, I was trying to take the default but it seems like I was misinformed about what the default is :p good to know
OK, thanks for all that, very helpful as always
Mark M.
you're welcome!
Aaron
LiveDataReactiveStreams still has not clicked for me, but hopefully once I go over your comments and think about it harder it'll click
don't have anything else for now - thanks and have a pleasant evening
Mark M.
the samples I cited above all use LiveDataReactiveStreams and so might be worth examining
you too!
Aaron
yes, I will do that
night
Aaron
has left the room
8:25 PM
Mark M.
turned off guest access

Saturday, December 8

 

Office Hours

People in this transcript

  • Aaron
  • Mark Murphy