Feb 6 | 8:20 AM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Feb 6 | 8:40 AM |
Dirk W. | has entered the room |
Feb 6 | 8:45 AM |
Dirk W. |
Good morning Mark
|
Mark M. |
hello, Dirk! sorry about the delay there
|
Mark M. |
how can I help you today?
|
Dirk W. |
no problem
|
Dirk W. |
I am from Germany. So, sorry in advance for any mistakes in my English writings.
|
Dirk W. |
I have some problems regarding Room and LiveData. Perhaps you can help me.
|
Mark M. |
I can try!
|
Dirk W. |
The app I am working on is about storing certain items in shelves.
|
Dirk W. |
I have a fragment to create or modify an existing item.
|
Dirk W. |
in this fragment I use observers to get data of the item to be modified and data of packaging units out of a room database. The itemdata fills several textfields and the data for the packaging units is used to fill a spinner both objects are connected by a ForeignKey.
|
Dirk W. |
In general this works fine. But from time to time I face some racing conditions. The observer of the packaging unit is too slow and won't get loaded before the fragment is visually created. In this case the spinner is not filled with data and causes several problems (object is null etc.).
|
Dirk W. |
I have some code here. Perhaps you can have a look and tell me, if I am doing something completely wrong or how I can prevent these race conditions.
|
Dirk W. | |
Mark M. |
are you retrieving the data in one @Query or two?
|
Dirk W. |
it's two different querys
|
Dirk W. |
View paste
|
Dirk W. |
and
|
Dirk W. |
View paste
|
Feb 6 | 8:50 AM |
Mark M. |
is caseId a field on VPEObject?
|
Mark M. |
in other words, is your foreign key relationship between the vpe and Items tables, based on that caseId?
|
Dirk W. |
no it's another object that is a parent of itemObject, also connected by a Foreing KEy
|
Dirk W. |
View paste
(3 more lines)
|
Dirk W. |
View paste
|
Dirk W. |
it's not based on the caseId but on vpeId
|
Mark M. |
the reason why I ask is because the most reliable way to get atomic results from Room is to use @Relation
|
Dirk W. |
atomic results means, that both objects are loaded at the same time?
|
Mark M. |
you would have a @Query that returned a LiveData<List<VPEAndItems>>, where VPEAndItems is a POJO
|
Mark M. |
yes
|
Mark M. |
VPEAndItems would have an @Embedded VPEObject and use @Relation for the List<ItemObject>
|
Dirk W. |
ok, understood
|
Mark M. |
however, I am not certain if you can construct a @Relation for your situation -- that is a more complex data structure than I have used with Room
|
Dirk W. |
do you think this is the only way or the best way to solve this?
|
Mark M. |
probably it is not the only way
|
Feb 6 | 8:55 AM |
Dirk W. |
I was thinking about embedding the VPEObject but through it away bacause of the complexity of the structure
|
Dirk W. |
throwed not through
|
Mark M. |
(FWIW, "threw" is English past tense for "throw")
|
Mark M. |
(English is weird)
|
Dirk W. |
thanks :-))
|
Mark M. |
another way to approach the problem is to try to handle it in the viewmodel
|
Mark M. |
in the end, ideally IMHO, the viewmodel is emitting the VPEObject and its ItemObjects at the same time
|
Mark M. |
the proposed @Relation approach would do that in the Room DAO
|
Mark M. |
if you have a repository layer between the viewmodel and the DAO, it could try to combine the results
|
Mark M. |
or, if you do not, the viewmodel could try to combine the results
|
Dirk W. |
yes, I have
|
Dirk W. |
in the viewModel:
|
Dirk W. |
View paste
|
Dirk W. |
oops, wrong method
|
Dirk W. |
View paste
|
Mark M. |
if this were RxJava, we would use a zip() operator to combine the results of the two queries, so downstream consumers would get the combined results when both results were ready
|
Dirk W. |
and in repository:
|
Dirk W. |
View paste
|
Feb 6 | 9:00 AM |
Dirk W. |
I am pretty new to Android programming and didn't 'dare' to look into RXJava
|
Mark M. |
you are using LiveData directly, and so you would need to find or write a zip() sort of "combiner" that would observe each LiveData and only emit something when both supplied a result
|
Mark M. |
it is possible that somebody has already written a zip() for LiveData -- I had a discussion in this very chat room a year or two ago with somebody who had a similar problem to yours
|
Mark M. |
he wound up writing a zip() method himself
|
Dirk W. |
I am not sure how I can combine both DAO calls in the respository
|
Mark M. |
you would wind up using a MutableLiveData or MediatorLiveData
|
Dirk W. |
ok. perhaps I will look into your archive
|
Mark M. |
I can understand the fear of RxJava
|
Dirk W. |
:-)
|
Mark M. |
in the long term, Kotlin and coroutines will be simpler for you to adopt, most likely
|
Mark M. |
personally, I would be going one of those routes, so that my fragment would get a "view state" containing all the data to be rendered
|
Mark M. |
however, it is possible that you could try to fix things in the fragment to be more friendly to data arriving at different times
|
Dirk W. |
Okay, I try to do that in the first step.
|
Dirk W. |
My problem is, that the spinner should be filled in the fragment
|
Dirk W. |
with the vpe (packaging unit)
|
Dirk W. |
before the fragment is shown
|
Mark M. |
um, that does not sound good
|
Mark M. |
you really do not have that kind of control over the timing
|
Dirk W. |
no, not really
|
Feb 6 | 9:05 AM |
Mark M. |
the typical approach is to have a "loading state" that gets displayed while you obtain the data, such as a ProgressBar
|
Mark M. |
then, replace that with the "real" UI once you are in position to display it
|
Dirk W. |
So, then I should check the loading state in both observers and only show the ui when both loadingstates are true, right?
|
Mark M. |
in your case, yes, if you cannot display anything with just the results of one
|
Mark M. |
that is why I like to combine the data earlier on (DAO/repository/viewmodel), so the fragment does not have to keep track of that
|
Dirk W. |
yes, but that sounds like a good idea
|
Dirk W. |
I will also check the combine solution. I am currently not quite sure hot to do it, but will have to read into MediatorLiveData
|
Mark M. |
I cover the older Architecture Components version of it in *Android's Architecture Components*
|
Mark M. |
which you can download or read online as part of your Warescription
|
Dirk W. |
yes I did and read through it, but not very closely looked at Mediator
|
Dirk W. |
some work for thi safternoon ;-)
|
Feb 6 | 9:10 AM |
Dirk W. |
View paste
|
Mark M. |
thanks for the kind words, and for subscribing!
|
Dirk W. |
have a good day
|
Mark M. |
you too!
|
Dirk W. | has left the room |
Feb 6 | 9:25 AM |
Mark M. | turned off guest access |