Apr 21 | 8:25 AM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Apr 21 | 8:30 AM |
Kai H. | has entered the room |
Mark M. |
hello, Kai!
|
Kai H. |
Hello again
|
Mark M. |
how can I help you today?
|
Kai H. |
I have a Fragment hosting two other Fragments, via a TabLayout and a Viewpager.
|
Kai H. |
The parent Fragment has an "save" button, which saves some data input in the child Fragments.
|
Kai H. |
The first child Fragment has some EditTexts. When being in the second Fragment and clicking "save" there will be a problem, as the first Fragment is ofc not accessible.
|
Mark M. |
the parent fragment should still have access to the first child
|
Kai H. |
There is a ViewModel for all three Fragments. I guess the question is how to best save the input from the EditText into the ViewModel when changing Fragments.
|
Apr 21 | 8:35 AM |
Mark M. |
you can register a listener on the TabLayout or the ViewPager to find about page changes
|
Mark M. |
the parent can then ask the child to ensure the ViewModel is up to date
|
Kai H. |
Are you sure? When changing to the second Fragment, onPause() is called for the first and when trying to access the first Fragments EditText, I get a NPE.
|
Kai H. |
Is using the listener a solid way to do it? It was one way I found.
|
Mark M. |
I don't know how you are accessing the first Fragment's EditText
|
Mark M. |
findViewById() will work between onCreateView() and onDestroyView()
|
Kai H. |
Another was to register to the EditText and just save every change.
|
Kai H. |
The third was throwing LiveData on it.
|
Mark M. |
LiveData cannot solve this problem on its own
|
Mark M. |
a TextWatcher on the EditText, and using it to update the viewmodel, is possible
|
Kai H. |
I do getActivity().findViewById(...) and it returns null.
|
Mark M. |
a fragment should never be doing getActivity().findViewById()
|
Mark M. |
call findViewById() on the fragment's own View, typically in onViewCreated()
|
Mark M. |
getActivity().findViewById() implies the ability to mess with widgets that are beyond the fragment itself
|
Mark M. |
(which isn't good)
|
Kai H. |
Ok
|
Apr 21 | 8:40 AM |
Kai H. |
I do feel that, rather than trying to get some field in a parent Fragment, the child Fragment should set the data via the ViewModel
|
Kai H. |
Which would imply using TextWatchers.
|
Mark M. |
TextWatcher is one approach, but the parent can also tell the child "hey, make sure the viewmodel is up to date" at appropriate points, such as when the tab changes
|
Mark M. |
the downside of TextWatcher is that it gets called frequently as the user types
|
Mark M. |
you can try to add some "debounce" logic to update the viewmodel, just not as frequently as TextWatcher gets called
|
Kai H. |
Yes, that is something I don't like.
|
Kai H. |
I was about to try using "onResume()" and "onPause()" inside the child to save away my contents.
|
Kai H. |
And set them
|
Mark M. |
to be honest, I forget what lifecycle callbacks get called when a ViewPager switches pages
|
Kai H. |
And advantages or disadvantages to the approach of the parent telling the child to save away the data?
|
Kai H. |
With ViewPager2 it seems to be those.
|
Mark M. |
that's surprising, if true
|
Mark M. |
I would have expected onAttach()/onDetach()
|
Mark M. |
onResume() and onPause() are supposed to be tied to the overall activity lifecycle
|
Mark M. |
but, I haven't played with ViewPager2 significantly yet
|
Mark M. |
regardless, updating the viewmodel in the right lifecycle methods should also be fine... but you will still need the ability for the parent to tell the child to update the viewmodel
|
Kai H. |
If you say the parent hooking into the viewpager and telling the children to save the data away is more robust, I'll do it that way.
|
Apr 21 | 8:45 AM |
Kai H. |
Why will I need that?
|
Mark M. |
I can't say whether or not it is more robust -- it's been years since I did that
|
Mark M. |
if the user is on the first tab and the user clicks save, you need to make sure that the first tab has updated the viewmodel before you use the viewmodel data for saving
|
Mark M. |
clicking save will not trigger any lifecycle callbacks on the first fragment
|
sudokai | has entered the room |
Kai H. |
Right. That would be the clean way I guess, better than trying to get the EditTexts from the parent Fragment.
|
Kai H. |
Hi sudokai
|
Mark M. |
yeah, the parent really should consider the child to be fairly opaque, rather than messing with its widgets directly
|
Mark M. |
let me take a question from sudokai, and I'll come back to you shortly
|
Mark M. |
sudokai: hi! how can I help you today?
|
Kai H. |
ofc
|
sudokai |
Hi, no questions for now. Just hanging out here in case.
|
Mark M. |
OK, if you come up with a question, let me know!
|
Mark M. |
Kai: back to you!
|
Apr 21 | 8:50 AM |
Kai H. |
Do you happen to have a "complex" ViewModel example?
|
Mark M. |
the app in *Exploring Android* is about as complex as I have
|
Kai H. |
The ones I could find so far are all quite simple and easy while the one I build is quite big.
|
Mark M. |
(in terms of public samples)
|
Kai H. |
Hm ok.
|
Mark M. |
on the whole, my focus is on "how to use these APIs" more than "how to assemble them into something large"
|
Mark M. |
because there are an infinite number of ways of doing the latter, any of which would be a headache to maintain
|
Kai H. |
I wonder if it's worth it at the end of the day, as I spend so much time making sure the ViewModel is in the right state at the right time.
|
Kai H. |
I would like to be able to say "this field is always the value of this EditText, this Field is always the value of this Checkbox, ..." and not have to deal with the details.
|
Mark M. |
the stateful UI of the Android view system does not make that very easy
|
Kai H. |
But I end up writing a lot of "boilerplate" code to make sure the right values get saved at the right time and such.
|
Mark M. |
two-way data binding was an attempt to address that, with its own problems and limitations
|
Mark M. |
Jetpack Compose gets rid of the stateful views, so the viewmodel (or other app-supplied state containers) is *the system of record* for what gets rendered
|
Mark M. |
but Jetpack Compose is 1-2 years away from being something you would want to use for mainstream stuff
|
Kai H. |
Especially for my mainstream stuff ;-)
|
Apr 21 | 9:00 AM |
Kai H. |
Do you think I should read through your first generation books or will the second generations books be enough?
|
Mark M. |
for general-purpose stuff, the second-generation books are better
|
Mark M. |
simply because they cover more up-to-date approaches
|
Kai H. |
I see. I started reading Android Architecture Components.
|
Mark M. |
but, the Warescription site search engine covers both generations
|
Mark M. |
mostly, that has been eclipsed by *Elements of Android Jetpack* and *Elements of Android Room*
|
Mark M. |
there are some Room things from *Android's Architecture Components* that I have not gotten into *Elements of Android Room*
|
Mark M. |
and there are probably some chapters in *Android's Architecture Components* with no equivalent in the second-generation books
|
Kai H. |
I actually skipped all but the first chapter on Room because I am not using that (yet).
|
Kai H. |
I see. So I should probably work my way through Jetpack instead.
|
Mark M. |
yes
|
Apr 21 | 9:05 AM |
Mark M. |
looking through my table of contents... most of the non-Room stuff in *Android's Architecture Components* is now in *Elements of Android Jetpack*
|
Mark M. |
with the benefits of being more up-to-date, showing Java and Kotlin, etc.
|
Apr 21 | 9:10 AM |
Kai H. |
Do you think Android is going strong in the future? Or will it be replaced by Flutter or even PWA?
|
Mark M. |
I think that you are conflating "Android" and "native Android app development"
|
Mark M. |
Android, the OS, can't be replaced by Flutter or PWAs
|
Mark M. |
native Android app development could, in theory
|
Apr 21 | 9:15 AM |
Mark M. |
I suspect that Flutter and PWAs each will be 5-10% of the Android app development space, and another 10% or so for various game frameworks (e.g., Unity 3D)
|
Mark M. |
Flutter and PWAs have a higher ceiling than do the game frameworks, simply because game frameworks are optimized for a specific domain (games)
|
Mark M. |
however, I don't anticipate that Flutter or PWAs will eclipse traditional Android app development any time soon
|
Apr 21 | 9:20 AM |
Kai H. |
That gives me more confidence to dive deeper into native Android development.
|
Apr 21 | 9:30 AM |
Mark M. |
OK, that's a wrap for today's chat!
|
Mark M. |
the transcript will go up on https://commonsware.com/office-hours/ in a few minutes
|
Mark M. |
the next chat is Thursday at 7:30pm US Eastern
|
Kai H. |
Have a good time everyone.
|
Mark M. |
have a pleasant day, and stay healthy!
|
Kai H. | has left the room |
sudokai | has left the room |
Mark M. | turned off guest access |