onCreateView called on non existing fragment - android

I am using fragments in Android. At the beginning the API seemed very easy to use. Now I can say that it is overcomplicated with many problems that are not clearly documented. For example following many tutorials, I have created two layout one for the portrait and one for the landscape. In the portrait I put just one fragment (list) while in landscape I also have the detail fragment.
If I rotate the device, onCreateView of detail fragment gets called (and it is ok). The problem is that, if I rotate again the device in portrait (with no detail fragment in the xml), the onCreateView of Detail fragment is called again! Why this? and how to avoid? I can check for ViewGroup container == null but it is terrible.
UPDATE: making some research, I found that if the fragment is in the layout with the tag this is called just once when the layout is not present while if you replace a FrameLayout present just in one layout with the fragment, then the onCreateView is always called. I was expecting it was not called if attached to a container that is not present
Thanks

Related

Show nested fragment on screen rotation without showing parent fragment

When rotating the screen my nested fragment is shown but for some brief moments, the parent fragment is also shown.
I have my MainActivity that has a FrameLayout with ID activity_base_container.
I'm doing this when my activity starts:
Fragment initialFragment = getInitialFragment();
mFragmentManager.beginTransaction()
.add(R.id.activity_base_container, initialFragment, initialFragment.getClass().getSimpleName())
.commit();
That initialFragment initial fragment is responsible to check some conditions and depending them will launch one of two possible fragments:
fragmentManager.beginTransaction().replace(R.id.activity_base_container, fragment, fragment.getClass().getSimpleName()).commit();
Lets assume it launches FragmentF (whit a root FrameLayout with id fragment_f_root). This fragments layout has a set of options. When the user clicks one of those options, the corresponding fragment is created and is launched like this:
//The example here is an option that displays a google map.
fragment = FragmentMapMultipleActivity.newInstance();
fragmentManager.beginTransaction()
.replace(R.id.fragment_f_root, fragment)
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
At this point all is working as expected. The problem is when I rotate the screen. FragmentF appears briefly and then immediately FragmentMapMultipleActivity, the nested fragment, appears.
Is it possible after rotating the screen show only the nested fragment or I should change my "architecture" to something else?
should change my "architecture" to something else?
Probably, you should.
The brightest Android-minds from Square are even advocating to avoid simple fragments everywhere it's possible: Advocating Against Android Fragments
Nested fragemnts, in its turn, increase complexity exponentially. The only good pattern of using them I've seen so far is ViewPager with it's FragmentPagerAdapter. In majority of other cases, consider using Custom Views instead.
It keeps your app's lifecycle cleaner and more predictable.
I don't think you can do much with this blinking you see, apart from:
setRetainInstance(true) and avoid full re-creation of the Fragment in Activity, so you keep you fragment's data during change of the configuration (and then pass same retained fragment to the fragment manager)
keeping layouts as lightweight as possible
avoid re-creation of already initialized variables
keep onViewCreate() as lightweight as possible
Good luck!

Fragments in are not restored after orientation change

In my program, I have the following hierarchy:
Activity
Fragment
ViewPager + FragmentStatePagerAdapter
Fragment containing video
The fragment that is nested immediately in the activity is initialized using setRetainInstance(true). This led to a crash whenever switching orientation. Used the solution described in the bug report: https://code.google.com/p/android/issues/detail?id=42601#c10.
Still, the app would crash whenever I would switch orientation. I found another bug report + solution: https://code.google.com/p/android/issues/detail?id=42601#c32.
After applying this solution I was able to rotate the device without the app crashing. However, the deeply nested fragment did not retain its state. As this fragment contains a video that should continue playing in spite of any orientation change, this is a must-have. I found a third bug report here describing this is a known issue in android support library versions 20 an up: https://code.google.com/p/android/issues/detail?id=74222#c17
Now, it does seem that the deepest fragment is retaining some kind of state. At least it is not destroyed, since the audio of the video keeps playing throughout and after the orientation change. However, the fragment is not restored after the orientation change. I simply see a white rectangle where the video should be.
As you can see, this is getting ridiculous. I have already had to use three hacky solutions to bugs in the ViewPager class, and it is still not working properly. If anybody has any idea what else I can try, I will be very much obliged.
Eventually, I did not find a solution to the problem. I have solved the problem by retaining the state of the nested fragments in the parent fragment, which does correctly retain state. To do this, I did the following:
Add a HashMap to the parent fragment
Gave every fragment a unique ID string that could be restored whenever the fragment was recreated
Created a state object for all nested fragments in their onCreate method and added it to the HashMap in the parent fragment. Or, if ((ParentFragment)getParentFragment()).stateMap.contains(id), restore the existing state.
Moved all member variables of the nested fragment to the StateObjects

Strange fragment behaviour - empty container in view hierarchy after screen rotation

I encountered very strange problem with fragments. In my case I have fragment which is placed inside activity. It has two type of layout:
layout - with Frame Layout with list_container id
layout-land - with two Layout: list_container and detail_container.
When user enters activity in portrait mode he sees TestListFragment. When he clicks one of the list element TestDetailFragment is added to backstack.
Next, when user rotates screen TestDetailFragment is removed from backstack and placed inside layout with id detail_container. How strange part appears, when inspecting view hierarchy there are two list_containers (one is empty and is over the rest of the content causing view overlap). onActivityCreated in TestFragment is triggered twice.
I'm including hierarchy view and screens:
http://i.imgur.com/cw37VX4.png
http://i.imgur.com/xQYalCJ.png
http://i.imgur.com/SObusj0.png
http://i.imgur.com/2sVhlIP.png
http://i.imgur.com/BCXrQ1K.png
Source code:
Activity with fragments: http://pastebin.com/2vAqQYgw
Activity layout: http://pastebin.com/iEawVBCx
TestFragment layout: http://pastebin.com/z5MZ5eR9
TestFragment layout-land: http://pastebin.com/RJHYRinM
Is this normal behavior? How to get rid of this layout?
When you nest fragments (i.e., have a fragment host a fragment), the child fragments need to be set up either by:
having the parent fragment inflate a layout containing <fragment> tags
having the parent fragment use getChildFragmentManager() when executing a FragmentTransaction to add the child fragments
In this case, the code in the question is using getActivity().getSupportFragmentManager(), not getChildFragmentManager().
To be honest, I cannot completely understand how this resulted in the cited symptoms, but according to the comments on the question, it helped.
When Android detect rotation it destroyes the running activity and create a new one, so if you have a behaviour on onCreate() and onDestroy() of the activity, keep in mind that. Take care also for Fragment that has a further event to manage and is related on the attached Activity onAttach()

Tab Swipe View in landscape, plain layout in portrait

My App is supposed to show a plain LinearLayout with a ListView and TextView when in portrait, but a SwipeView with three tabs when in landscape. The layout is to be changed whenever the orientation of the phone is changed.
I get that normally you'd just have two layout files for portrait and lanndscape but I feel that won't be sufficient in my case. After all the Tab and Swipe functionality requires more than just an XML file. While looking for solutions to my problem it was suggested starting a new activity in the onConfigurationChanged() method, but at the same time this was stated to be very bad practice leading to all sorts of problems.
Now I thought about adding a whole lot of if-else statements to my TagActivity.java always checking what the current orientation is and spawning whatever is needed. Would this be a good way to do it? Is it possible to have multiple onCreate() Methods, one for each orientation?
Any input would be greatly appreciated!
The tutorial I used to implement the TabActivity was the one from androidhive:
http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/
I did something similar in a recent project. We ended up using a view pager with PagerSlidingTabStrip (https://github.com/astuetz/PagerSlidingTabStrip/issues/5). In portrait only show one fragment in the view pager and hide the tabs, and in landscape populate out the view pager and tabs. Not sure if this works in your particular situation (it seems like it would), but food for thought.

Android Layout is overlapping itself

I am using fragments in my app. Below is the screenshot of my app. Everything looks fine on activity launch. But, when I change the screen orientation, the layout overlaps itself while scrolling. Any ideas what is wrong?
EDIT (Solution):
I found out what was wrong. A new fragment was added on orientation change. I was previously using fragmentTransaction.add(...), I replaced it with replace method.
For future vistor's understanding...
You are most likely adding your fragment in your activity's onCreate().
When your device is rotated, your activity is destroyed and re-created, but it also recreates any added fragments.
With these two things in mind...
onCreate is called and you add a fragment to your activity. You have one fragment.
You rotate the screen.
The activity is destroyed and re-created. Your fragment is destroyed and recreated. You still have one fragment.
Your activity calls onCreate() as a part of its recreation, which adds a fragment to your activity. You now have two fragments.
If one or both of your fragments have transparent backgrounds, both may display at once, as is likely the case here.
Either use replace instead of add (which you have done), or better, only add the fragment in onCreate() if savedInstanceState is null. If it is null it means it's the first onCreate() call.

Categories

Resources