Mark M. | has entered the room |
Mark M. | turned on guest access |
Jun 5 | 4:20 PM |
Igor P. | has entered the room |
Mark M. |
hello, Igor!
|
Mark M. |
how can I help you today?
|
Igor P. |
Greetings Mark!
|
Igor P. |
I have a couple of questions if you allow
|
Igor P. |
first
|
Jun 5 | 4:25 PM |
Igor P. |
in our app we have a complex structure of activity hosting a fragment hosting a view pager which page hosts a fragment with another view pager which of course hosts fragments
|
Mark M. |
that's... complicated :-)
|
Igor P. |
a little
|
Igor P. |
the upper most pager has turned of swipes
|
Igor P. |
but the question is about fragment managers
|
Igor P. |
from different places in the stack i described above we need to add/replace fragments at different levels
|
Igor P. |
so since i pass child fragment managers to each view pager we have several fragment managers in use
|
Igor P. |
and the question is: which fragment manager should i use to do fragment transactions at different levels of the stack described above?
|
Mark M. |
the one that is managing (directly) the fragments that you wish to add/replace
|
Mark M. |
at least, I presume that's the appropriate answer
|
Mark M. |
I'd be willing to put up with a fair bit of physical torture, just to avoid using nested fragments
|
Igor P. |
hm
|
Jun 5 | 4:30 PM |
Igor P. |
:)
|
Mark M. |
what you don't want to do is attempt to mess with the fragments that are the pages in the pagers
|
Mark M. |
assuming that you are using FragmentPagerAdapter or FragmentStatePagerAdapter
|
Mark M. |
they really don't like it when outsiders mess with their fragments
|
Igor P. |
yes, i know this requires additional effort, i try to avoid that
|
Mark M. |
I had to roll my own PagerAdapter implementation (ArrayPagerAdapter) just to try to handle simple scenarios like adding, moving, and removing pages
|
Mark M. |
from your description, the only fragment I see that is not a page in a pager is the root one
|
Igor P. |
but if i use fragment managers directly managing fragments i may well end up with nesting a fragment within a fragment
|
Igor P. |
yes, the only independent one is the root one
|
Mark M. |
oh, your described structure has to use nested fragments
|
Mark M. |
just don't ask me to write that code, or debug it, or be within 100km of it, etc. :-)
|
Mark M. |
any time you are using getChildFragmentManager(), you are nesting fragments, even if there is a pager "in between" them
|
Igor P. |
at the time being i've tried doing getActivity().getSupportFragmentManager() to get the FM to do transactions. from any place within my structure. and it seems to work well. or does it only seem like that?
|
Jun 5 | 4:35 PM |
Mark M. |
that's not how it's supposed to be done
|
Mark M. |
now, it's conceivable that your code will survive, at least for a while
|
Mark M. |
however, I'll raise my minimum distance to 250km :-)
|
Igor P. |
:)
|
Igor P. |
could you suggest what may go wrong with this approach?
|
Mark M. |
ummm... rupture in the space-time continuum?
|
Mark M. |
more seriously, I am surprised that manipulating the same fragment via different managers even works
|
Igor P. |
sounds bad ))
|
Mark M. |
you said in your original description that you used "child fragment managers", which I assume means getChildFragmentManager()
|
Igor P. |
yes
|
Igor P. |
i pass this to the view pager adapters
|
Mark M. |
if in one spot you, say, add() a fragment using getChildFragmentManager(), and later on you try to remove() that fragment using the activity's top-level FragmentManager... if that works, it's a minor miracle
|
Igor P. |
because until i did this pages would never get onStop() and so on on the fragment hosting the pager being replaced...
|
Mark M. |
yes, well, this is one of the reasons why I avoid nested fragments -- they are full of strange behavior
|
Mark M. |
it's probably one of the reasons they didn't release the capability for a couple of years after originally introducing fragments
|
Jun 5 | 4:40 PM |
Igor P. |
with all these difficulties i lean towards the judgement that a ViewPager was never designed to handle tabs at the root level of an application
|
Igor P. |
but only to swipe between the details fragments at the leaf level
|
Mark M. |
I would more generally phrase it that nested ViewPagers scare me about as much as nested fragments
|
Mark M. |
so, if you want tabs at the top level, versus a nav drawer, that's fine, but then don't try having tabs-within-tabs, or something like that
|
Igor P. |
right
|
Mark M. |
if you have that complicated a navigation structure, probably go with a nav drawer anyway for the top-level navigation
|
Igor P. |
ok, thanks, i'll review the design again and see if i can do anything with it
|
Igor P. |
let's move on
|
Jun 5 | 4:45 PM |
Igor P. |
another one on the topic of passing serializable (parcelable) data to activities/services within the same app
|
Jun 5 | 4:45 PM |
Igor P. |
assuming i have a local (same process) service and i pass something serializable with an intent
|
Mark M. |
pass how?
|
Igor P. |
putExtra(...)
|
Igor P. |
on an Intent
|
Mark M. |
no, I mean, how are you using the Intent?
|
Igor P. |
to start a service for example
|
Mark M. |
OK
|
Igor P. |
or put something serializable in a bundle to pass to a bound service with a message
|
Igor P. |
does the payload really gets serialized in this case?
|
Mark M. |
it should
|
Igor P. |
assuming it is a local service
|
Mark M. |
the only case where an Intent is used pass-by-reference that I know of is LocalBroadcastManager
|
Mark M. |
now, when you say "pass to a bound service with a message", what do you mean?
|
Igor P. |
in our app we have a bound service
|
Igor P. |
with handlers on each side
|
Igor P. |
so we have 2-way communication using messengers
|
Jun 5 | 4:50 PM |
Igor P. |
and we pass serializable objects with the messages
|
Jun 5 | 4:50 PM |
Mark M. |
oh
|
Mark M. |
um, to be honest, I'm not sure if the Intent is pass-by-reference or pass-by-value there
|
Mark M. |
IOW, whether it actually crosses process boundaries
|
Mark M. |
stuff like startActivity() and startService() always cross a process boundary
|
Mark M. |
even if the starter and the start-ee are in the same process
|
Igor P. |
i've noticed that after de-serialization we get a reference to the very same object as before the serialization. so we can change object state from both sides...
|
Mark M. |
if I had to guess, my hope is that Messenger recognizes that it is in the same process and therefore does not have to convert the Intent into a Parcel
|
Mark M. |
then presumably the Intent is pass-by-reference
|
Mark M. |
you get that same sort of problem with LocalBroadcastManager
|
Mark M. |
I haven't used Messenger much, so I don't recall ever looking at its implementation
|
Igor P. |
i think that if it was indeed serialized we would get a copy of the object on the other side...
|
Mark M. |
agreed
|
Igor P. |
ok, then it should be the case, thanks
|
Igor P. |
i reckon the parcelable has the same behaviour, doesn't it
|
Igor P. |
?
|
Mark M. |
it should
|
Igor P. |
i see
|
Igor P. |
and the last one, if we have some time...
|
Mark M. |
we have a few more minutes
|
Igor P. |
is there a good approach to implement custom back key navigation in the app?
|
Jun 5 | 4:55 PM |
Mark M. |
what do you mean?
|
Igor P. |
if we need to override default back key behaviour
|
Mark M. |
override onBackPressed() in the activity
|
Igor P. |
say, navigate to a sibling tab instead of exiting the applicaton
|
Mark M. |
personally, I'm not a fan of BACK meaning movement between tabs
|
Mark M. |
you wouldn't see that in a Web app, for example
|
Mark M. |
that being said, onBackPressed() is the right way to implement it
|
Mark M. |
for example, if you try using SlidingPaneLayout for a master/detail pattern, it doesn't offer automatic BACK button support, so you handle it yourself in onBackPressed()
|
Igor P. |
in the Activity?
|
Mark M. |
yes
|
Mark M. |
I don't recall fragments getting called with onBackPressed()
|
Igor P. |
they don't
|
Igor P. |
and i will need to somehow pass the event through view pagers to fragments...
|
Igor P. |
and nested fragment.. )
|
Igor P. |
this is doable, but is complicated
|
Igor P. |
any other good ideas to capture back keys closer to the top of the stack?
|
Mark M. |
I've avoided messing with the BACK option via anything other than onBackPressed()
|
Jun 5 | 5:00 PM |
Mark M. |
I don't even know if it raises a KeyEvent when BACK is in the navigation bar
|
Igor P. |
can't recall
|
Igor P. |
ok, it's clear
|
Igor P. |
thanks for your help!
|
Mark M. |
you are very welcome
|
Mark M. |
and that's a wrap for the chat
|
Mark M. |
this transcript will be posted to https://commonsware.com/office-hours/ shortly
|
Igor P. |
it is
|
Igor P. |
cheers!
|
Mark M. |
the next chat is Tuesday at 7:30pm US Eastern
|
Mark M. |
have a pleasant day!
|
Igor P. |
same to you!
|
Igor P. | has left the room |
Mark M. | turned off guest access |