Is there any way to clean up fragments' state?
I mean such situation:
I create a fragment instance (lets call it A) passing it an ID to load some content, than return to previous fragment (B for example). And when I go to A again, passing NO ID (it should than load default data) - it already has an ID from previous usage and my logic breakes.
Do not add your 'A' to backstack. So it will not be saved into backstack. Whenever you go back and come again it will not be added. Is this what you want right.
// Instantiate a new fragment.
Fragment newFragment = CountingFragment.newInstance(mStackLevel);
// Add the fragment to the activity, pushing this transaction
// on to the back stack.
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.simple_fragment, newFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
//ft.addToBackStack(null);// Do not add to backstack here.(add every time new).
ft.commit();
Related
I have a problem with the backstack behaviour. That is what I am doing:
add(fragment1) + addToBackStack(null)
replace(fragment2) + addToBackStack(null)
What is happening:
Fragment 1 is added and in the backstack
Then the second fragment replaces the first one and it is added to the backstack.
Now I want to change my last backstacked fragment with a new transaction which put a new backstack fragment so:
[frag1, frag2] becomes [frag1, frag3]
but this transaction made by a popBackStack + replace is making the frag1 to load by calling its onCreateView and onActivityCreated. I know this is the expected behaviour since this is how backstack works, but I am trying to find a way to avoid this preload.
Edit
In this question I am using the concept of backstack fragment for the transaction to be more clear. Every transaction here is an add+remove (which is a replace).
The code for replace I am using is:
public int replaceFragment(BaseFragment newFragment, boolean addToBackStack, boolean animated, PopStackMode popMode) {
if (popMode != null) {
getSupportFragmentManager().popBackStack(newFragment.getFragmentTag(), popMode == PopStackMode.POP_INCLUSIVE ? FragmentManager
.POP_BACK_STACK_INCLUSIVE : 0);
}
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (animated) {
ft.setCustomAnimations(R.anim.slide_in_left, 0, R.anim.slide_out_right, 0);
}
ft.replace(R.id.fragment_container, newFragment, newFragment.getFragmentTag());
if (addToBackStack) {
ft.addToBackStack(newFragment.getFragmentTag());
}
return ft.commit();
}
You can see I am creating a navigation history based on the fragment backstack, as it was kind of a browser. When a "page" is added there is a fragment and a backstack transaction. In this context, I trying to:
Remove the current fragment.
Remove the transaction from the backstack.
Add a new fragment without poping and loading the previous backstack fragment.
I hope it is more clear.
Edit 2
I have filled a request feature for a flag that supports this behavior. Find it here.
First, you should understand that the backstack doesn't save fragments, but it saves transactions instead. When you call popBackStack what it actually does is revert the previous transaction. More on this here.
I think that you can do this:
Name your transactions by providing a unique name to your addToBackStack instead of null. i.e. addToBackStack("frag1").
Don't call popBackStack + replace, but instead just call replace.
Then, in your activity, override your onBackPressed and if the current fragment being displayed is Frag3 (you can check this using findFragmentByTag if you provided a tag in the replace method) you can call getSupportFragmentManager().popBackStackImmediate("frag1", FragmentManager.POP_BACK_STACK_INCLUSIVE); (otherwise call the super.onBackPressed)
Hello I am working with sliding menu with fragment.
Indivisual fragment works properly. But suppose user navigates From fragment A->B , now 'B' works perfect and now if user goes from B->A than fragment 'A' is called from onAttach() .
I want such a condition if any fragment is opened , than reopening it should not load whole fragment , it should be resumed just like we handle activity with Intent.FLAG_ACTIVITY_REORDER_TO_FRONT.
Here is my code...
FragmentManager fm = MainActivity.this.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Layout1 fragment = new Layout1();
ft.add(R.id.activity_main_content_fragment, fragment,Layout1.class.getName());
ft.addToBackStack(Layout1.class.getName());
ft.commit();
Answer updated:
Reading the documentation, there is a way to pop the back stack based on either the transaction name or the id provided by commit. Using the name may be easier since it shouldn't require keeping track of a number that may change and reinforces the "unique back stack entry" logic.
Since you want only one back stack entry per Fragment, make the back state name the Fragment's class name (via getClass().getName()). Then when replacing a Fragment, use the popBackStackImmediate() method. If it returns true, it means there is an instance of the Fragment in the back stack. If not, actually execute the Fragment replacement logic.
private void replaceFragment (Fragment fragment){
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();
}
}
If you return to a fragment from the back stack it does not re-create the fragment but re-uses the same instance and starts with onCreateView() in the fragment lifecycle, see Fragment lifecycle.
So if you want to store state you should use instance variables and not rely on onSaveInstanceState()
Check this link. it will help How to resume Fragment from BackStack if exists
I have android screen layout shown below
Apps screen divided into 3 fragments, Header, Footer and Content. Header and Footer fragments are fixed. Content fragment is changing according to content. I replaces fragment1-fragment3 according to need. Initially Fragment1 is shows in content area. When i press a next button fragment1 is replace by fragment2. This is the order. I have question, if i press another button previous, how can i return to previous fragment ( fragment2 -> fragment1). Is any built in mechanism available in fragment class.
Please guide me...
thanks in advance
try this code
FragmentTransaction tx = fragmentManager.beginTransation();
tx.replace( R.id.fragment, new MyFragment() ).addToBackStack( "tag" ).commit();
Whenever you try to call new fragment then add back stack for it through
ft.addToBackStack(null);
And now if you want to back from one fragment to another then, make one method..
public void DeleteCurrentFragment()
{
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment currentFrag = getSupportFragmentManager().findFragmentById(R.id.detailFragment);
String fragName = "NONE";
if (currentFrag!=null)
fragName = currentFrag.getClass().getSimpleName();
if (currentFrag != null)
transaction.remove(currentFrag);
transaction.commit();
}
And after that call this:
getSupportFragmentManager().popBackStack();
DeleteCurrentFragment();
you can try something like:
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.add(R.id.contentFragment, <your fragment>);
ft.addToBackStack(null);
ft.commit();
so suppose you're on fragment1 and after doing some stuff you want push fragment2 then on your contentFragment you can add or replace the fragment (fragment2 in this case) as per your requirement. Now when you call addToBackStack it means add this transaction to the back stack. So that the transaction will be remembered after it is committed, and will reverse its operation when later popped off the stack. Internally it maintains a stack so you don't want to do anything. At last when you press back button from fragment2 it checks whether the transaction having any fragment in its stack, if yes then it calls it. Its like top of stack. When you call addToBackStack in that stack fragment1 is added. So when you press back button stack's top is fragment1 so it calls it.
It happens when you press hardware back button. If you want to do this on any button, then on that button's click listener simply onBackPressed() method.
I am struggling with the structure of the fragment, Thing is... In Activity there is two fragments. One contains a list. Call this FragmentA. The other contains detail. Call this FragmentB.
With every list item in FragmentA there is a different view for FragmentB, so what is the preferred way to handle this kind of scenario?
Thank You
Without seeing the complexity of the app in question, I would suggest that each different view for FragmentB be represented in its own fragment.
The use the Fragment Transaction method to replace the placeholder (let's call this R.id.fragment_container) where FragmentB is with the appropriate fragment depending on your selection in FragmentA. Something like this:
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
I'm currently using a ViewGroup (SwipeyTab implementation) to switch between Fragments. However, some Fragment "pages" get replaced by other Fragments on the same Tab, so I initially tried:
FragmentTransaction ft = fragment.getFragmentManager().beginTransaction();
ft.remove(currentFragment);
ft.add(newFragment,"");
ft.commit();
That code would remove the current fragment but not add newFragment (from Logcat, it would get instantiated but not appear).
I ended up adding it in the FragmentPagerAdapter.getItem(int position) call based on current state (based on this: Replace Fragment inside a ViewPager). However, I'd like to be able to add each newly replaced fragment to be part of the back stack.
I tried adding to backstack before removing the fragment:
currentFragment.getFragmentManager().beginTransaction().addToBackStack(null).commit();
FragmentTransaction ft = fragment.getFragmentManager().beginTransaction();
ft.remove(currentFragment);
ft.commit();
and that didn't work - it added the last fragment to the backstack, so when I pressed back, it would just reload the current fragment.
Is there anyway I can add a fragment to the backstack that has been replaced in the "non traditional" way?