Android Fragments not being recreated on Activity Restart - java

I have an Activity which contains a couple of nested Fragments. I have been having a lot of trouble handling orientation changes. Something is not correct when the Activity tries to recreate itself which causes the app to crash. If I try to debug the code during an orientation change the app crashes without any messages in the logcat.
My problem seems to be the the runtime is trying to recreate the fragments in my Activity when I don't want it to. None of the fragments have setRetainInstance(true) so they shouldn't be getting kept.
I have added logging to the onCreate and onDestroy methods of the Activity and Fragments. When the app first runs I get the following output:
Activity onCreate
Fragment1 onCreate
Fragment1 onCreateViewStart
Fragment1 onCreateViewEnd
Fragment2 onCreate
Fragment2 onCreateViewStart
Fragment2 onCreateViewEnd
I then rotate the device and get the following:
Fragment1 onDestroy
Fragment2 onDestroy
Activity onDestroy
Fragment1 onCreate
Fragment2 onCreate
Activity onCreate
Fragment1 onCreateViewStart
Fragment1 onCreateViewEnd
Fragment2 onCreateViewStart
Fragment2 onCreateViewEnd
Fragment2 onDestroy
Fragment2 onCreate
After the last message above the app crashes with the following exception message:
E/FragmentManager(32258): No view found for id 0x7f0a0047 (com.appName:id/fragmentHolder) for fragment Fragment2{6529b910 #6 id=0x7f0a0047 16002}
Why are my fragments being recreated automatically? Is there anything I can do to force the activity to reload as if the app was being started for the first time when the orientation changes? Is this not how the life cycle is supposed to work in the first place?
I can add any code if requested.

The FragmentManager is responsible for managing the fragments and
adding them to the activity's view hierarchy.
The FragmentManager handles two things:
A list of fragments.
back stack of fragment transactions.
To add, remove, attach, detach or replace fragments in the fragment list you use Fragment Transactions.
When you ask the FragmentManager for a fragment using findFragmentById() or findFragmentByTag(), if the fragment is
already in the list, the FragmentManager will return it. Then you can
use it.
Knowing that. If there are fragments added to the FragmentManager's list when the orientation change happens, those fragments are going to be recreated automatically in order to recreate the view hierarchy as it was before the orientation change. If you don't want a fragment to be recreated, remove it from the list using a fragment transaction.

You know how if you background an app and then reopen it? The Activity instances are still there with the Bundle savedInstanceState populated with data. This means that the OS is recreating your app from a serialised state rather than from scratch.
What you need to do in the case where savedInstanceState is not null is look use your FragmentManager to findFragmentByTag.

Related

how to finish fragment on single activity app android

I have a Splash_Screen fragment. After navigating to the next fragment, I want my SplashScreen fragment to be destroyed. How can I do this?
I use getActivity().finish and this finishes my app.
Once you move from Splash_Screen Fragment to next fragment,Remove Your Splash_Screen Fragment form 'BACKSTACK'. So Your Splash_Screen Fragment will not open again.
How this works for you.
For more information see below thread from Stack Over Flow:
How to clear Fragment backstack in android

Fragments always go through onAttach to onDestroyView, instead of onCreateView to onDestroyView

I am using 4 fragments in 1 activity. The navigation is done via NavDrawer. Every time I navigate through the fragments, each fragment goes through the following methods:
onAttach() to onDestroyView()
I was expecting them to go through these once and then go through onCreateView() to onDestroyView() but this is not happening.
I would like to initialize certain things only once in onCreate() but now I cannot.
Does anybody have any experience with this?
Hi Thanks for the reply.
I found the problem. I was creating a new fragment in the nav drawers itemselect. To solve it I created an instance of each fragment in main activity and just set this to current fragment instead of creating a new one.
Thanks again

Move from Activity to Fragment when button clicked

I used this code to move from Activity to Fragment when button clicked but when I run this code I find Activity is still in background.
TopicsFragment fragment = new TopicsFragment();
android.support.v4.app.FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.welcome_id, fragment);
transaction.commit();
First of all, you need to understand what Activity and Fragments are. You cannot move from Activity to Fragment.
You can inflate a Fragment or Fragments into an Activity. Fragments cannot be independent from an activity.
A fragment must always be hosted in an activity and the fragment's
lifecycle is directly affected by the host activity's lifecycle. For
example, when the activity is paused, so are all fragments in it, and
when the activity is destroyed, so are all fragments. However, while
an activity is running (it is in the resumed lifecycle state), you can
manipulate each fragment independently, such as add or remove them.
When you perform such a fragment transaction, you can also add it to a
back stack that's managed by the activity—each back stack entry in the
activity is a record of the fragment transaction that occurred. The
back stack allows the user to reverse a fragment transaction (navigate
backwards), by pressing the Back button.
Source: https://developer.android.com/guide/components/fragments
If you don't want to see the activity after entering into fragment, you could extend from DialogFragment and make it fullscreen, there are many examples, google it using "android fullscreen dialogfragment".
and here is DialogFragment doc.

Android - onBackPressed has no effect from fragment

I have one Activity with a viewpager in it and also a frameLayout which is used as a container for fragments that should be drawn above this viewpager.
When I click a button of my Activity a fragment is shown in that framelayout container. On a press in the navigation bar I can close this fragment. All these things work fine when called from the activity itself.
I have now the situation that on a specific action from one of the fragments in the viewpager I invoke a callback which the main activity implements and then shows a fragment in the frame layout.
But here now comes the problem. When I want to navigate back or rather want to close the fragment like I described before, nothing happens.
So in conclusion:
"Fragment show to container" invoked from Activity directly -> I can navigate back from the fragment by getActivity().onBackpressed()
"Fragment show to container" invoke from fragment in viewpager and then delegated to activity -> The navigation back or getActivity().onBackpressed() has no effect.
So my question is: How can I close the fragment in the container even when I call it from one the fragments inside the viewpager of the activity?
Probably you are adding a fragment to the backstack, so onBackPressed you should pop last fragment from the backstack.
Something like that:
FragmentManager fm = activity.getFragmentManager();
fm.popBackStackImmediate();
Meanwhile I found the problem..
Due to the fact that I am running some kind of update loop, I added the fragments multiple times to the backstack but didn't realize it because the fragment itself didn't change, the new instances just got added to the backstack. So when I called the onBackpressed() method the instances got removed from the backstack but because there were like 200 of them nothing happened.

On view page listener inside a fragment

is there a way when i'm inside a fragment to listen when the specific fragment i'm changed?
for example when i swipe to another fragment i want to show a toast that said "Fragment Swiped,Data Saved".
like an OnClose but only when the fragment lost the foucus
the ViewPager calls the setUserVisible(boolean) method when the fragments are swiped. You can use that.

Categories