GLee GLee - 18 days ago 7
Android Question

Best way to switch between two fragments

I'm interested in the best way to have a single activity that switches between two fragments.

I've read probably 15 Stack Overflow posts and 5 blogs posts on how to do this, and, while I think I cobbled together a solution, I'm not convinced it's the best one. So, I want to hear people's opinions on the right way to handle this, especially with regards to the lifecycle of the parent activity and the fragments.

Here is the situation in detail:


  1. A parent activity that can display one of two possible fragments.

  2. The two fragments have state that I would like to persist across a session, but does not necessarily need to be persisted between sessions.

  3. A number of other activities, such that the parent activity and the fragments could get buried in the back stack and destroyed due to low memory.

  4. I want the ability to use the back button to move between the fragments (So as I understand it, I can't use setRetainInstance).



In addition to general architecture advice, I have the following outstanding questions:


  1. If the parent activity is destroyed due to low memory, how do I guarantee that the states of both fragments will be retained, as per this post: When a Fragment is replaced and put in the back stack (or removed) does it stay in memory?. Do I just need a pointer to each fragment in the parent activity?

  2. What is the best way for the parent activity to keep track of which fragment it is currently displaying?



Thanks in advance!

Answer

I ended up adding both of the fragments using the support fragment manager and then using detach/attach to switch between them. I was able to use commitAllowingStateLoss() because I retain the state of the view elsewhere, and manually set the correct fragment in onResume().

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);    

    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    fragmentTransaction.add(R.id.my_layout, new AFragment(), TAG_A);
    fragmentTransaction.add(R.id.my_layout, new BFragment(), TAG_B);
    fragmentTransaction.commit();
}

public void onResume() {
    super.onResume();
    if (this.shouldShowA) {
        switchToA();
    } else {
        switchToB();
    }
}

private void switchToA() {
    AFragment fragA = (AFragment) getSupportFragmentManager().findFragmentByTag(TAG_A);
    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    fragmentTransaction.detach(getSupportFragmentManager().findFragmentByTag(TAG_B));
    fragmentTransaction.attach(fragA);
    fragmentTransaction.addToBackStack(null);

    fragmentTransaction.commitAllowingStateLoss();
    getSupportFragmentManager().executePendingTransactions();
}
Comments