JJD
JJD

Reputation: 51834

Fragment which is not top most in backstack is resumed

Given the application flow show in the graphic and textually described in the following.

Application flow

  1. Fragment 1 is the lowest fragment but not in the backstack by setting disallowAddToBackStack.
  2. Fragment 2 is pushed onto the stack, using fragmentTransaction.addToBackStack().
  3. A new instance of fragment 1 is pushed onto the stack.
  4. The top most fragment (fragment 1) is popped from the stack.
  5. Activity 2 becomes foreground.
  6. Activity 1 becomes foreground.

Here is the generalized method I use to handle fragments:

private void changeContainerViewTo(int containerViewId,  Fragment fragment, 
                                   Activity activity, String backStackTag) {

    if (fragmentIsAlreadyPresent(containerViewId, fragment, activity)) { return; }
    final FragmentTransaction fragmentTransaction = 
                 activity.getFragmentManager().beginTransaction();
    fragmentTransaction.replace(containerViewId, fragment);
    fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    if (backStackTag == null) {
        fragmentTransaction.disallowAddToBackStack();
    } else {
        fragmentTransaction.addToBackStack(backStackTag);
    }
    fragmentTransaction.commit();
}

Problem

When activity 1 resumes in the last step the lowest instance of fragment 1 also resumes. At this point in time fragment 1 returns null on getActivity().

Question

Upvotes: 5

Views: 3397

Answers (3)

Jim Baca
Jim Baca

Reputation: 6132

Android OS can and will create and destroy fragments when it sees fit. This is likely happening when you launch Activity 2 and return to Activity 1. I'd verify for sure that it isn't the actively displayed fragment. What is probably happening is that you are seeing it do some of the creation steps for fragment 1 before it does the creation steps for fragment 2.

As for handling the detached fragments you should take a look at this page. The gist of it is that you should only be using the getActivity in certain fragment functions(Based on the fragment life cycle). This might mean that you have to move some of your logic to other functions.

Upvotes: 1

Jorge Gil
Jorge Gil

Reputation: 4355

When an Activity is not showing UI and then come to show UI, the FragmentManager associated is dying with all of your fragments and you need to restore its state.

As the documentation says:

There are many situations where a fragment may be mostly torn down (such as when placed on the back stack with no UI showing), but its state will not be saved until its owning activity actually needs to save its state.

In your Activity onSaveInstanceState and onRestoreInstanceState, try saving you Fragment references and then restore them with something like this:

public void onSaveInstanceState(Bundle outState){
    getFragmentManager().putFragment(outState,"myfragment", myfragment);
}
public void onRetoreInstanceState(Bundle inState){
    myFragment = getFragmentManager().getFragment(inState, "myfragment");
}

Try this out and have luck! :-)

Upvotes: 2

salfon
salfon

Reputation: 306

I don't see how this would happen, unless (based on how you described the steps) you've misunderstood how fragmentTransaction.addToBackStack() works: it manages which transactions are placed in backstack, not fragments.

From the android docs:

By calling addToBackStack(), the replace transaction is saved to the back stack so the user can reverse the transaction and bring back the previous fragment by pressing the Back button.

So if your step 2 looked something like this in code:

fragmentTransaction.replace(containerViewId, fragment2);
fragmentTransaction.addToBackStack();
fragmentTransaction.commit();

and your step 3:

fragmentTransaction.disallowAddToBackStack()//or just no call to addToBackStack - you do not say
fragmentTransaction.replace(containerViewId, newfragment1);
fragmentTransaction.commit();

At this point, Fragment2 will be removed from the backstack, and your backstack consists of the two Fragment1 instances. in Step 4 you pop the top one, which means you should have the bottommost Fragment1 now at the top.

This explains why it is the resumed fragment if you return to the activity. But not, i'm afraid, why it is apparently detached from its activity.

Upvotes: 1

Related Questions