Mark M. | has entered the room |
Mar 19 | 8:25 AM |
Mark M. | turned on guest access |
Mar 19 | 8:30 AM |
sudokai | has entered the room |
Mark M. |
hello, sudokai!
|
Mark M. |
how can I help you today?
|
Mar 19 | 8:35 AM |
sudokai |
Hi again Mark.
|
sudokai |
I'm still building my ViewModel tracking my uploads. What's the best practice to observe different streams of LiveData?
|
sudokai |
I want to track an upload or an item, but each item can contain pictures
|
Mark M. |
so, do you mean that you have a LiveData for some base upload, plus additional LiveData for each picture upload, or something like that?
|
sudokai |
Ideally I would like to have a single LiveData of the view state
|
Mark M. |
I agree
|
Mar 19 | 8:40 AM |
Mark M. |
what are you using for the actual uploads? OkHttp?
|
Mar 19 | 8:40 AM |
sudokai |
So it's a single centralized upload status bar that shows the state of the upload
|
Mar 19 | 8:40 AM |
sudokai |
Like "Uploading pictures 3/20...."
|
sudokai |
The upload status bar is for the item (the container)
|
sudokai |
Then each item has N pictures
|
sudokai |
Yeah, I'm using OkHttp
|
sudokai |
Then I'm saving the upload state inside Realm
|
Mark M. |
OK, and you said that you are using LiveData in your ViewModel -- what are you using between OkHttp/Realm and the LiveData? just callback APIs?
|
sudokai |
I'm using this: https://academy.realm.io/posts/android-architec...
|
Mark M. |
OK, so Realm is giving you its own LiveData
|
sudokai |
So I have UploadState and PictureUploadState inside realm
|
sudokai |
And then I use the technique described in the article to get LiveData from Realm
|
sudokai |
But then I need to combine those in some way to output a single stream of LiveData for the ViewModel
|
Mar 19 | 8:45 AM |
Mark M. |
LiveData is not very powerful. I tend to rely on it for the "last mile", going from a ViewModel to an activity/fragment, and use RxJava or Kotlin coroutines for all the repository/data source work.
|
Mark M. |
however, you should be able to set up what you want with a MediatorLiveData
|
Mark M. |
MediatorLiveData allows you to have it subscribe to N other LiveData and call you when any of those change, so you can apply an update to the MediatorLiveData itself
|
sudokai |
Basically, my realm is set up as this
|
sudokai |
View paste
|
sudokai |
Okay I'll check it out
|
sudokai |
Thanks!
|
Mark M. |
so, in your case, you would have the MediatorLiveData observe each LiveData associated with the overall operation (base + N pictures), and the MediatorLiveData would emit updates to the viewstate based on that overall operation
|
sudokai |
Okay, that makes sense, so I need to create N streams
|
sudokai |
Stepping back, is this general approach the right one?
|
Mark M. |
yeah, I am assuming that you are getting one LiveData from Realm for each of your states
|
Mark M. |
I have not used Realm much, so I do not know its API very well
|
sudokai |
Would you do it this way or? I'm using LiveData because it's what I know
|
Mar 19 | 8:50 AM |
Mark M. |
in terms of your "stepping back" question... again, I would tend to use RxJava or coroutines with Realm and OkHttp, and have my ViewModel consume those and update LiveData as needed
|
Mark M. |
LiveData is not designed for "heavy lifting", as it were
|
Mark M. |
so, the more complex things get, the amount of work that you will need to do for a 100% LiveData solution will climb faster than the equivalent amount of work for a RxJava/coroutines + LiveData solution
|
sudokai |
So you would emit LiveData from the ViewModel - Fragment communication but use RxJava / coroutines for ViewModel - Realm communication?
|
Mark M. |
yes, though I don't know how well Realm and coroutines get along
|
Mark M. |
(again, I'm not a Realm guy)
|
Mark M. |
Realm and RxJava can work together, though at least a couple of years ago there were some screwy Realm threading issues
|
sudokai |
Tbh, I'm a newbie myself. I would probably just use Room if I started a new project, but I inherited this one.
|
sudokai |
Realm's entire paradigm seems a bit strange to me
|
Mark M. |
in my case, the project I was on was slowly ripping out Realm and replacing it with Room
|
sudokai |
Though it might just be my own ignorance
|
sudokai |
We have a lot of weird Realm issues appearing on Crashlytics
|
Mark M. |
I wasn't a huge fan of what I was seeing with Realm, and I really wasn't a fan of the big APK footprint it required
|
Mark M. |
in the hands of a Realm expert, Realm is probably fine -- we were in a similar situation to you, having inherited a Realm-based project, and we were happy to be getting rid of it
|
Mar 19 | 8:55 AM |
sudokai |
I'll check if I can track a single Realm stream. The PictureUploadState is nested inside the UploadState.
|
sudokai |
That would simplify things a lot. But I doubt it's possible.
|
Mark M. |
¯\_(ツ)_/¯
|
sudokai |
It's tracking the N streams that worries me
|
sudokai |
Because the user can add pictures to be uploaded while the other stuff is still uploading
|
sudokai |
And also delete pictures
|
Mark M. |
that sounds like more of a "work queue" model
|
Mar 19 | 9:00 AM |
sudokai |
But I cannot use a single state object to track the entire upload, because each picture has its own upload state, the number of retry attempts, etc.
|
Mark M. |
makes sense
|
sudokai |
I'm offloading the uploads themselves to workmanager from the viewmodel
|
Mark M. |
and in the Worker you are doing the OkHttp calls?
|
sudokai |
Yeah, exactly. So each worker does the OkHttp calls and creates/updates state objects in Realm
|
Mark M. |
so it sounds like you are tracking N pieces of WorkManager work
|
Mark M. |
WorkManager is set up fairly well for that scenario, as I recall
|
sudokai |
Then, from the viewmodel I query Realm and listen to the state object changes
|
Mark M. |
ah, I'd probably monitor WorkManager
|
Mark M. |
though perhaps there is data in Realm that you would need that you would not be getting from your WorkManager results
|
Mark M. |
but, off the cuff, if you are trying to report to the user the results from N pieces of work, to me that's "observe WorkManager" more than "observe Realm"
|
Mar 19 | 9:05 AM |
sudokai |
Yeah, I was just checking your book
|
sudokai |
LiveData<WorkInfo>
|
sudokai |
That's promising
|
Mark M. |
right
|
sudokai |
I also see MediatorLiveData
|
sudokai |
So you launch WorkRequests and keep adding sources to the MediatorLiveData
|
sudokai |
Nice approach
|
Mark M. |
in your case, if you tag them all the same, getWorkInfosByTagLiveData() will give you a single LiveData that emits a List<WorkInfo>, presumably updating when any single piece of work changes state
|
Mark M. |
that would be an alternative to using MediatorLiveData to handle N individual LiveData per piece of work
|
sudokai |
Then the realm state object could just hold the upload attempts and timestamps and whatnot
|
sudokai |
But wouldn't be used for stream observation
|
Mar 19 | 9:10 AM |
Mark M. |
yes, probably
|
Mark M. |
I say "probably" just because I'm not 100% clear on your needs, but my guess is that observing WorkManager and perhaps making some Realm queries in response to WorkManager state changes will meet your needs
|
Mark M. |
IOW, the usual caveats apply: your mileage may vary, do not taunt Happy Fun Ball, etc. :-)
|
sudokai |
Thanks! I'll try this approach. Sounds like the most manageable one!
|
Mar 19 | 9:30 AM |
Mark M. |
OK, that's all the time I have for today's chat
|
Mark M. |
the transcript will go up on https://commonsware.com/office-hours/ shortly
|
Mark M. |
the next chat is Saturday at 4pm US Eastern
|
Mark M. |
have a pleasant day, and stay healthy!
|
sudokai | has left the room |
Mark M. | turned off guest access |