0

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.

droidpl
  • 5,872
  • 4
  • 35
  • 47
  • 1
    You could use nested fragments to assign a container fragment at each back stack layer that you may wish to tamper with, and just change the child fragment. – corsair992 Feb 18 '15 at 17:41
  • Unless it sound good, what happends if y replace the view from the parent in the container and I add the transaction to the backstack? It will recreate the view as it is doing now. I would need a new container on top of the one I am using for the navigation to add this behaviour. Isn't it? – droidpl Feb 19 '15 at 08:51
  • I didn't really understand your question, but the nested child replacement should not be added to the back stack. The container itself would be a layer on the back stack, and the child would be dynamically replaceable (without tampering with the back stack). – corsair992 Feb 19 '15 at 09:10

1 Answers1

0

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:

  1. Name your transactions by providing a unique name to your addToBackStack instead of null. i.e. addToBackStack("frag1").
  2. Don't call popBackStack + replace, but instead just call replace.
  3. 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)
Community
  • 1
  • 1
Joao Sousa
  • 4,055
  • 1
  • 26
  • 29
  • As far as I know this shouldn't work since if I don't call popBackStack this transaction will remain there. My requirements are not so simple than 2 frament, there is 7 different fragments that can be there. I am actually assigning a name (the canonical name of the fragment class) . Please have a look at the code I am really using for replace, I edited the answer. – droidpl Feb 18 '15 at 12:46
  • You're right, the transaction will remain there, but because you're providing a name to the `popBackStack` method, as you can see in the [documentation](http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack) it'll pop every transaction until the one you provide is found. Anyway, since you admit that you are trying to achieve a workaround from the expected behaviour, I advise you to rethink your solution. – Joao Sousa Feb 18 '15 at 12:55
  • The problem is the requirements itself. Only one activity, navigation using fragments. it is horrible, but that is what they want. So I can assume there is no way to avoid the previous transaction to be loaded or take all the transactions, pop all of them and re-add all except the one I hate – droidpl Feb 18 '15 at 12:59
  • You could add an argument to the fragment once you navigate away from it, and then check if that argument is present or not in the onCreateView, but that is algo an ugly workaround. – Joao Sousa Feb 18 '15 at 13:05
  • Sure, it is horrible :( Anyway I think it should be a flag to avoid preloading the fragment when you make a popBackStack if you want. Maybe I will fill a feature on the platform, should not be difficult to add it since they have a flagged pop right now. – droidpl Feb 18 '15 at 13:08
  • I have filled a request feature https://code.google.com/p/android/issues/detail?id=151923&thanks=151923&ts=1424265466, vote for it if you consider it usefull – droidpl Feb 18 '15 at 13:18