Apr 7 | 8:20 AM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Apr 7 | 8:30 AM |
Jan S. | has entered the room |
Jan S. |
Good morning!
|
Mark M. |
hello, Jan!
|
Mark M. |
how can I help you today?
|
Apr 7 | 8:35 AM |
Jan S. |
I am used SharedPreferences and it all works but probably not efficient. Currently I just read the file whenever any fragment or activity needs to use one of the values. Should I read the file once and put it in a singleton class. Then only write back to the file when a value changes. And then I suppose I'd make the singleton as a live data. So the UI can change accordingly.
|
Mark M. |
SharedPreferences are automatically cached by the framework
|
Mark M. |
by which, I mean a SharedPreferences object reads the XML once
|
Mark M. |
not every time you retrieve values from it
|
Mark M. |
so, having the SharedPreferences itself be mediated by a repository or some other singleton should be sufficient
|
Jan S. |
So the reference to the shared preferences should be in a singleton and that's it?
|
Apr 7 | 8:40 AM |
Mark M. |
personally, I would wrap the SharedPreferences in a repository object, as otherwise you wind up leaking details of how things get stored to the rest of your app
|
Mark M. |
but you do not need to read all the data out of the SharedPreferences into some other object to have it be cached -- caching the SharedPreferences itself would be sufficient
|
Jan S. |
So the getBoolean, getString calls etc. would be made from the repository and the repository uses the cached shared preferences. Do I understand that right?
|
Mark M. |
yes
|
Mark M. |
now, if you want a reactive API (LiveData, RxJava, coroutines, etc.), then you may wind up reading data out of the SharedPreferences into a model object to emit via that API
|
Mark M. |
however, that's more of an API design issue, more so than a caching one
|
Apr 7 | 8:50 AM |
Jan S. |
View paste
|
Mark M. |
no, sorry
|
Mark M. |
I have poked at that problem a few times and have not come up with a solution
|
Mark M. |
(other than to not use their factory directly -- usually I use Koin and inject my viewmodels)
|
Jan S. |
Okay. The factory is easy to use but Koin looks easy too.
|
Apr 7 | 8:55 AM |
Kai H. | has entered the room |
Kai H. |
Hello
|
Mark M. |
hello, Kai!
|
Mark M. |
Jan: let me take a question from Kai, and I'll return to you shortly
|
Mark M. |
Kai: how can I help you today?
|
Kai H. |
I wonder how "legacy" inter-Fragment communication looked like
|
Mark M. |
we used clay tablets :-)
|
Kai H. |
Let's say there is a tab host with two fragments and the information of one should be accessible in the other
|
Kai H. |
Well, I hope not ;-)
|
Kai H. |
But nowadays one would probably use a ViewModel
|
Mark M. |
yes, a shared viewmodel at the activity level would be a typical approach nowadays
|
Mark M. |
classically, we would have the activity implement an interface
|
Mark M. |
fragments would cast getActivity() to that interface
|
Mark M. |
then call methods on the interface
|
Mark M. |
(the interface isn't strictly necessary -- you could cast to the activity class itself -- but it is nice in case you might have more than one activity host the fragment in the future)
|
Apr 7 | 9:00 AM |
Kai H. |
My Activity is a very "general" class that will call a lot of different fragments
|
Kai H. |
Preferably I would not have to adapt that.
|
Mark M. |
preferably, I would have hair
|
Mark M. |
:-)
|
Kai H. |
So I guess I'll use ViewModel, even if it's not used at all in this app yet.
|
Kai H. |
And introduce something new.
|
Mark M. |
given a choice between introducing ViewModel or using the legacy approach, I would lean towards ViewModel
|
Mark M. |
the legacy approach was a bit fragile with respect to lifecycle event timing
|
sudokai | has entered the room |
Kai H. |
It's a party!
|
sudokai |
Hi people :)
|
Kai H. |
Hi kai
|
Jan S. |
We are all on lockdown.
|
sudokai |
Working remotely though!
|
Jan S. |
So no place else to party. But yes, easy to work remote.
|
Mark M. |
Kai: let me give the others a quick turn, and I'll try to get back to you in a bit
|
Mark M. |
sudokai: how can I help you today?
|
Apr 7 | 9:05 AM |
Kai H. |
Did you find your code today, sudokai? ;-)
|
sudokai |
I have a more general question
|
sudokai |
On Jetpack Navigation
|
sudokai |
Do you have any samples on using Jetpack Navigation and bottom tabs?
|
Mark M. |
no, sorry
|
Mark M. |
mostly because bottom tabs is part of the Material Components for Android IIRC
|
sudokai |
How are you supposed to set up your nav graph in this case?
|
Mark M. |
I haven't done that personally, though I recall there was a section in the docs specifically on that
|
sudokai |
Okay, I'll try to look it up
|
Mark M. | |
sudokai |
Go ahead with your other questions people!
|
Mark M. |
OK... Jan, your turn! do you have another question?
|
sudokai |
Oh thanks for the link!
|
Jan S. |
No, nothing.
|
Mark M. |
OK, if you come up with one, let me know!
|
Mark M. |
Kai: back to you! do you have another question?
|
Apr 7 | 9:10 AM |
Ashish D. | has entered the room |
Mark M. |
hello, Ashish!
|
Mark M. |
Kai: do you have another question, or can I turn to Ashish?
|
Kai H. |
You can turn to Ashish
|
Mark M. |
OK
|
Mark M. |
Ashish: everyone else has had a turn asking questions, so... it's your turn! how can I help you today?
|
Ashish D. |
Hello Mark, hope you are doing well. I have a small query.
|
Ashish D. |
I tried the example where we can just pass the layout file in the fragment, does it require some specific settings, as I was not able to do that/
|
Mark M. |
I am not certain which example you are referring to
|
Ashish D. |
*passing layout file in fragment constructor
|
Ashish D. |
That was from somewhere else
|
Apr 7 | 9:15 AM |
Mark M. |
there is nothing stopping you from supplying a layout resource ID to a fragment, such as via the arguments Bundle, then having the fragment use LayoutInflater to inflate() that resource
|
Mark M. |
I have not done that in quite some time, personally, but I recall using that technique a couple of times years ago
|
Ashish D. |
ok, no issue. That was it from my side. Thanks. I really appreciate your efforts. Glad to have you among us.
|
Mark M. |
OK
|
Mark M. |
at this point, if anyone has any questions, go right ahead!
|
Kai H. |
Right now I have several variables in my Fragment that later get put into an object which in turn will be passed to a method. I wonder if those variables should move to the ViewModel or if I should put the whole object there.
|
Mark M. |
that's tough to answer in the abstract, but my gut says if they eventually need to be combined, you may as well have the ViewModel hold onto the combined object
|
Kai H. |
I collect all the information and then there is like 20 lines of code just doing object.setDate(...) and object.setUserId(...).
|
Apr 7 | 9:20 AM |
Mark M. |
either the ViewModel could have a method that takes those parameters and combines them, or the fragment could combine them and hand the object over to the ViewModel
|
Mark M. |
my preference is to have as little code in activities and fragments as possible, as testing them is annoying
|
Mark M. |
so I'd lean towards having the ViewModel assemble the object from the pieces
|
Kai H. |
I don't even test, but my preference would be to have the ViewModel abstract all the setters and getters away
|
Kai H. |
And kinda wrap the target object.
|
Kai H. |
I was just wondering if I would run into any problems doing it like this.
|
Mark M. |
¯\_(ツ)_/¯
|
Kai H. |
:D
|
Kai H. |
\o/
|
Mark M. |
again, that's difficult to answer in the abstract, and "it depends" isn't exactly a useful response...
|
Kai H. |
Yes. I was hoping for something like "it failed me once when I did foo in situation bar"
|
Mark M. |
I can sometimes provide that for more concrete scenarios
|
Kai H. |
It's hard to make it more concrete
|
Kai H. |
I would have to have thought about it more in advance
|
Mark M. |
oh, that's completely understandable
|
Mark M. |
it's more that I can help with some types of questions here better than others
|
Kai H. |
The Activity for my fragments is a very general activity that is used by like 20 other fragments as well. Will I not run into problems using the activity as a key for the ViewModel for my two specific fragments?
|
Mark M. |
(again, if anyone has questions, feel free to ask! it's a free-for-all time for the rest of the chat!)
|
Mark M. |
I don't thik so
|
Mark M. |
er, I don't think so
|
Apr 7 | 9:25 AM |
Kai H. |
Ok. Looking forward to playing around with it.
|
Apr 7 | 9:25 AM |
Mark M. |
now, over time, if you start to use ViewModel with more of those fragments, you may want to have a bunch of focused ViewModels rather than one massive ViewModel that you try to use with all the fragments for all the work
|
Kai H. |
Well, I would only have one ViewModel per connected Fragments
|
Kai H. |
And right now it would be the second pair of connected Views. The other pair is not even two fragments, but somehow something else which I don't understand yet.
|
sudokai |
Okay, see you all next time! Thanks for the help!
|
Kai H. |
I guess the question is how to get different ViewModels even though I'm passing in only one Activity.
|
Kai H. |
Have a good one and stay healthy
|
Mark M. |
a ViewModel is indexed by class, within a particular provider
|
Kai H. |
Ok
|
Mark M. |
so, if you need logically-distinct ViewModels, have them be separate classes
|
Mark M. |
so, if Fragment A and Fragment B need to share data, that is one ViewModel, with the activity (or hosting fragment) being the supplier of the provider
|
Mark M. |
but if Fragment A also needs its own local ViewModel, that is a separate class, using Fragment A's own provider
|
Kai H. |
I see
|
Apr 7 | 9:30 AM |
Kai H. |
Thanks :)
|
Mark M. |
and if later Fragment C and Fragment D need to share data, for stuff that is not related to Fragment A and B, that's a third ViewModel class, activity-scoped
|
Mark M. |
lather, rinse, repeat
|
Mark M. |
and that's a wrap for today's chat
|
Jan S. |
Thank you Mark. Have a good day.
|
Mark M. |
the next chat is Thursday at 7:30pm US Eastern
|
Kai H. |
Stay healthy everyone
|
Mark M. |
have a pleasant day, and stay healthy!
|
Jan S. | has left the room |
Kai H. | has left the room |
sudokai | has left the room |
Ashish D. | has left the room |
Mark M. | turned off guest access |