Office Hours — Today, May 12

Saturday, May 9

May 12
7:20 PM
Mark M.
has entered the room
7:25 PM
Mark M.
turned on guest access
7:30 PM
Kai H.
has entered the room
Mark M.
hello, Kai!
how can I help you today?
Kai H.
Hello Mark!
By answering some questions, I hope?
Mark M.
I can try!
no promises!
:-)
Kai H.
No pressure
roberto
has entered the room
Kai H.
I have actually been fighting to implement a Dialog with DialogFragment :D
Mark M.
(BTW, hello, Roberto! I will be with you shortly!)
Kai H.
I ended up doing it with a callback that I would re-set in onCreateView by grabbing the DialogFragment with findViewByTag(...).
And I wondered if there is a "modern" way to do it.
Mark M.
I guess I do not understand the scenario. What is the callback for?
Kai H.
To get the "onPositiveButton" into the calling Fragment.
Mark M.
OK, so your concern is: how do you get results from the DialogFragment to the Fragment that displayed it?
Kai H.
The result sharing was done with a ViewModel. It was the submit/ok event that I needed somehow.
I tried with LiveData but couldn't get it to work.
7:35 PM
Mark M.
LiveData on its own, since it is a value holder, is not great for events that you want to consume exactly once, not once per configuration change
Kai H.
And had the feeling that I misused LiveData for an event there and shouldn't do that.
Mark M.
the original solution, and the one that I profile in a couple of spots in books, is the "single live event" pattern
this is an somewhat-officially-sanctioned hack for using LiveData for events (in that Google engineers first proposed it)
if you are using Kotlin, you could use a BroadcastChannel for this sort of thing, and my slow-in-coming *Elements of Kotlin Coroutines* update will explore that a bit
in a Java app, though, I'd use the single live event pattern, as the least-bad option
Kai H.
Is that in Exploring Jetpack too?
Mark M.
possibly, give me a minute to hunt around...
hmmm... perhaps not
yet another thing to consider covering there...
Kai H.
Ok. That's the one I am currently reading and I just wondered if I missed it.
But I do have access to Exploring Android too ;-)
Mark M.
callbacks can work, but you need to be careful that both fragments are talking to the right other fragment, after a configuration change
7:40 PM
Mark M.
and a viewmodel holding a reference to a fragment is architecturally icky
Kai H.
Yes. And I really don't like the extra setup stage and stuff
I actually hold the reference to the parent Fragment in my DialogFragment
Mark M.
let me take a question from Roberto, and I will return to you in a bit
Kai H.
sure
Mark M.
Roberto: your turn! how can I help you today?
roberto
Hello Mark, how is going?, I'm implementing an ObjectRepository / NetworkBoundResource following Google's Guide to app architecture (https://developer.android.com/jetpack/docs/guide)
In the guide they implement this NetworkBoundResource which takes care of fetching objects from network and updating database. It's used by the repository.
I know it's not part of your books and this may not be a good question but perhaps you can give some guidance
The question is
that I would like to avoid using MediatorLiveData in the NetworkBoundResource and avoid callbacks hell
Are you expliring the use of coroutines for cases like this in your books/examples?
r/expliring/exploring
Mark M.
yes, at least to an extent
my take on the ever-popular to-do app -- the subject of *Exploring Android* -- uses coroutines for all the repository/data source stuff
7:45 PM
Mark M.
at the viewmodel, those get adapted to LiveData for consumption by the UI layer
7:45 PM
roberto
Great, that's exactly what I want to do
Mark M.
however, there, the focus is on the Room-based local data source
my only network bit is more of an import operation than an ongoing sync
mainly because I *really* don't want to have to maintain a Web service and accounts and stuff for that book :-)
roberto
haha, makes sense. Ok. I'll check that example
Mark M.
in *Elements of Kotlin Coroutines*, particularly the upcoming long-awaited 0.2, I'll be exploring this a bit more
and I have some Retrofit examples here and there, though in those cases mostly without a local database
roberto
I'm actually reading the Elements of Kotlin Coroutines version is published, I'm quite enjoying it. You made me remember the DLL version issues... that was very deep and forgotten on my memory :D
Mark M.
yeah, fun times (not)
the only example that I can think of that uses both is the weather app in the current *Elements of Kotlin Coroutines* that grabs weather forecasts from the US National Weather Service and inserts them into a Room database, plus displays the Room contents in a RecyclerView
that's in the hands-on tutorial appendix
but all of that is still fairly trivial in scope
roberto
Ohh.. that's interesting. I'll check that too
It might be what I need because I think I know what I want to do... just need to fill some conceptual gaps and know how to wire everything
7:50 PM
roberto
Do you have an estimated date new version of Elements of Kotlin Coroutines new version?
7:50 PM
Mark M.
hopefully a bit less than a month
let me take another question from Kai, and I'll come back to you in a bit
Kai: back to you! do you have another question?
roberto
Great, thanks Mark
Kai H.
Do you have (an) example(s) of a "wizard" in any of your books?
Mark M.
you mean a sequential series of screens, with forward/back options? then no, sorry
Kai H.
Yes, that is what I mean.
Mark M.
if you mean a dude with a long pointed beard and a hat with moons and stars on it, then no, sorry
Kai H.
There seems to be no "canonical" version out there.
Mark M.
:-)
Kai H.
Neither? Huh.
Mark M.
you'll find some referred to as "steppers", a name which I assume comes from some other platform
but yeah, Google never published one and I am not aware of a single "go-to" implementation
Kai H.
I think there should totally be a bearded dude in one of your books somewhere.
Mark M.
I'd have to hire an illustrator -- my drawing skills are... ummm... lousy
Kai H.
You said in the last office hours that you use them sometimes, so I was wondering.
7:55 PM
Mark M.
I haven't needed one in about 18 months, and I forget if we used a library or just some fragments for that one
Kai H.
Is it an uncommon use case?
Mark M.
looking at the roadmap for my current client, we'll probably be needing one for a revised "onboarding" experience in the coming months
it's not uncommon, but the precise presentation usually varies
which then raises the issue: what exactly is the library going to do for you?
Kai H.
You mean what I try to achieve?
There is a "start a new task" thing in our app, which requires several pieces of input from the user.
Mark M.
it's more that I suspect that a lot of places can't use a library because the library implements one look-and-feel and their designer wants something else
if you subtract out the navigation elements of the wizard (forward/back, perhaps dot indicators for place in the sequence), there really isn't a lot to a wizard
Kai H.
Oh ok. So one would do something with ViewPager2 and possibly Navigation?
Mark M.
classically, a ViewPager would be a common base
I haven't yet had a need for ViewPager2, and I don't know how it would blend with Navigation (or if that's even practical)
so it might be either ViewPager2 (with pages per wizard step) or Navigation (with plain fragments per wizard step but using Navigation to step between them)
8:00 PM
Mark M.
the modern take on a wizard implementation is something I'm likely to need to chase down here soonish, but I haven't had to yet
Kai H.
Okay
Mark M.
let me take another one from Roberto, and I'll come back to you afterward
Roberto: over to you! do you have another question?
8:05 PM
Mark M.
Roberto: if you come up with another question, let me know!
in the meantime...
Kai: back to you! do you have another question?
Kai H.
I think I do :)
I was tempted to do a ViewModelFactory to be able to pass parameters to the constructor of a ViewModel and wondered if you end up with lots of ViewModels and ViewModelFactories in a normal app.
Mark M.
I only have so much experience with "normal apps", so I can't really answer that
Kai H.
I have two ViewModels so far and wanted to do that for both (ended up having a "initializeIfNotInizialied(...)" method on one).
Mark M.
also, if you use a dependency inversion framework (Dagger, Koin, etc.), you often wind up creating ViewModels differently
the DI framework basically has the factory, either "out of the box" or via some glue code that you create
roberto
Mark, no questions, thanks for your help. I'm already reading the examples you mentioned.
Mark M.
Roberto: OK, sounds good!
Kai: so my guess is that relatively few projects implement a lot of factories, because projects that big probably are using some form of DI
Kai H.
So once I start using dependency inversion I will probably not stumble over the "parameterized ViewModel" problem so much anymore?
Mark M.
it's more that you'll get it for free (more or less) as part of DI, at least for injectable stuff
Kai H.
I see. So kinda looking forward to start learning about and using DI
Mark M.
my client projects have been using Dagger, and it's the heavyweight industrial-strength solution
Kai H.
In the meantime I guess I'll just initialize my ViewModels with a method if I really need initialization
8:10 PM
Mark M.
yeah, particularly in a Java-centric project, until you want to climb Mount Dagger, your choices are annoying factories or skipping that sort of initialization
Google is supposed to be coming out with some Dagger improvements to help with usability, which will be interesting
Kai H.
Is such a way of initialization a code small or does it have any big downsides that you can think of?
Mark M.
in Kotlin, particularly for smaller projects, Koin is very nice
the biggest challenge probably is in configuration changes
if the data you are supplying is immutable, the fact that you call the method a couple of times may not matter
Kai H.
I actually is in my case.
Mark M.
if the data that you are supplying is mutable, though, now you have a problem, as the viewmodel needs to know whether to use the value it has or the value you are re-handing it
Kai H.
Ok
Mark M.
in your case, then, so long as that method is idempotent (you can call it N times without issue), you should be OK
Kai H.
Another question if I may?
Mark M.
fire away!
8:15 PM
Kai H.
We have a "Session" object in our app, which holds a couple of caches, a connection and such. I wondered if that would be a Repository in modern app development.
Repository as the green box in "Android Architecture" by google
Mark M.
one or more repositories, yes
Kai H.
Sorry, orange Box
I guess in a bigger app one would end up with more than one repository?
Mark M.
the projects that I have worked on with repositories tend to have several, based on the data they work with
Kai H.
Divided by the kind of data that they hold?
Mark M.
right
having a single massive repository becomes a testability nightmare
Kai H.
Could you give a quick example on the data?
I figured. It's really tempting to have a "god repository" (as it is to have a god session object).
Mark M.
gods have a tendency to fling lightning bolts through your codebase
anyway... suppose we were creating an online bookstore, named after a major river
having one repository handle books and orders and bookmarks/favorites and customer profile data and all that would be too much
8:20 PM
Mark M.
you would wind up with thousands upon thousands of lines of code in a single class
it doesn't have to be "one repository per entity", but it's closer to that than "one repository per app"
Kai H.
So you would have a repository for each
Mark M.
I would be leaning in that direction
but, for example, suppose that the app had favorites and history
from a UI standpoint, those might be presented a lot differently, but in terms of data storage, they probably are very similar
so, having those in one repository might be reasonable, particularly if there are operations that affect both types simultaneously
Kai H.
Would a repository often be a singleton?
Mark M.
hah, I just commented on that very topic a couple of hours ago on Stack Overflow
"Repositories, where used, are almost always singletons. However, ideally, they are managed by a dependency inversion framework (Dagger, Koin, etc.) rather than being ordinary static Java fields, Kotlin object, etc. That way, the consumers of the repositories can use mocks or fakes in testing. The repository itself then often delegates to "data store" objects for saving things to files, databases, the Web service, etc. The repository handles details of converting between models used by the main app and the objects needed by those data stores (e.g., Room entities, Retrofit types)."
Kai H.
Link pls :D
8:25 PM
Mark M.
Kai H.
Thanks.
So much to learn
Mark M.
yep
Kai H.
Can be quite overwhelming
Mark M.
I remember when I first taught a week-long Android course, back in 2009, and how much ground I could cover (maps! audio/video playback! WebView!)
things got complicated in the intervening decade
it's almost like people are expecting their apps to be well-written or something
Kai H.
Not on my watch!
Mark M.
ummmm....
Kai H.
;-)
Mark M.
LOL
8:30 PM
Mark M.
anyway, that's a wrap for today's chat
the next one is Thursday in the 8:30am US Eastern slot
Kai H.
Have a good time everyone
Mark M.
see ya!
Kai H.
has left the room
roberto
has left the room
Mark M.
turned off guest access

Saturday, May 9

 

Office Hours

People in this transcript

  • Kai Hatje
  • Mark Murphy
  • roberto