Office Hours — Today, April 7

Saturday, April 4

Apr 7
8:20 AM
Mark M.
has entered the room
Mark M.
turned on guest access
8:30 AM
Jan S.
has entered the room
Jan S.
Good morning!
Mark M.
hello, Jan!
how can I help you today?
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
by which, I mean a SharedPreferences object reads the XML once
not every time you retrieve values from it
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?
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
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
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
however, that's more of an API design issue, more so than a caching one
8:50 AM
Jan S.
View paste
Do you know how to get rid of that pesky unchecked cast error on ViewModelFactory? Google search says to use an annotation so it doesn't show.  But seems like there should be a better way. Unchecked cast: ContentViewModel to T on this code: 
class ContentViewModelFactory(private val application: Application) :
    ViewModelProvider.Factory {
    override fun <T: ViewModel> create(modelClass:Class<T>): T {
        return ContentViewModel(application) as T
    }
}
Mark M.
no, sorry
I have poked at that problem a few times and have not come up with a solution
(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.
8:55 AM
Kai H.
has entered the room
Kai H.
Hello
Mark M.
hello, Kai!
Jan: let me take a question from Kai, and I'll return to you shortly
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
Well, I hope not ;-)
But nowadays one would probably use a ViewModel
Mark M.
yes, a shared viewmodel at the activity level would be a typical approach nowadays
classically, we would have the activity implement an interface
fragments would cast getActivity() to that interface
then call methods on the interface
(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)
9:00 AM
Kai H.
My Activity is a very "general" class that will call a lot of different fragments
Preferably I would not have to adapt that.
Mark M.
preferably, I would have hair
:-)
Kai H.
So I guess I'll use ViewModel, even if it's not used at all in this app yet.
And introduce something new.
Mark M.
given a choice between introducing ViewModel or using the legacy approach, I would lean towards ViewModel
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
sudokai: how can I help you today?
9:05 AM
Kai H.
Did you find your code today, sudokai? ;-)
sudokai
I have a more general question
On Jetpack Navigation
Do you have any samples on using Jetpack Navigation and bottom tabs?
Mark M.
no, sorry
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!
Kai: back to you! do you have another question?
9:10 AM
Ashish D.
has entered the room
Mark M.
hello, Ashish!
Kai: do you have another question, or can I turn to Ashish?
Kai H.
You can turn to Ashish
Mark M.
OK
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.
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
That was from somewhere else
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
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
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(...).
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
my preference is to have as little code in activities and fragments as possible, as testing them is annoying
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
And kinda wrap the target object.
I was just wondering if I would run into any problems doing it like this.
Mark M.
¯\_(ツ)_/¯
Kai H.
:D
\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
I would have to have thought about it more in advance
Mark M.
oh, that's completely understandable
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!)
I don't thik so
er, I don't think so
9:25 AM
Kai H.
Ok. Looking forward to playing around with it.
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
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.
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
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
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
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
lather, rinse, repeat
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

Saturday, April 4

 

Office Hours

People in this transcript

  • Ashish Dhiman
  • Jan Smith
  • Kai Hatje
  • Mark Murphy
  • sudokai