Search code examples
androidandroid-fragmentsback-stack

How can I maintain a child view's state when switching fragments?


I am having a hard time understanding how the fragment lifecycle relates to switching between fragments in the back stack. Please bear with me if my question exposes more than one misconception.

Here is my code:

public class SomeFragment extends Fragment {
    private SomeCustomView customView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.some_fragment, container, false);
        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // Create the child view
        customView = (SomeCustomView) getView().findViewById(R.id.some_fragment_child_view);
        customView.initializeMyCustomView();
    }
}

As you can see, my fragment has a child view. The child view is a custom one. Here's code:

public class SomeCustomView extends SurfaceView implements SurfaceHolder.Callback {

    private boolean aVariableWhichMustPersistForLifetimeOfApplication;

}

Whenever this fragment is added to the back stack and then later restored, the variable customView is recreated, and so I loose the value of aVariableWhichMustPersistForLifetimeOfApplication. This is creating all sorts of problems for me.

The application started out using an Activity that only displayed SomeCustomView and there were no fragments. Now I have to add functionality and so I have turned the custom view into a fragment, and thus I arrive at this problem.


Solution

  • I found an answer which works for me. The FragmentTransaction class has a number of methods which allow you to switch fragments in/out. (Android documentation for FragmentTransaction is here and a great StackOverflow explanation is here.)

    In my case, I wanted SomeFragment to never loose the data contained in its view. To do this, use this code:

    SomeFragment fragment = new SomeFragment();
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.add(R.id.activity_fragment_placeholder, fragment, "some_fragment");
    transaction.commit();
    

    and then later:

    getFragmentManager().beginTransaction().hide(fragment).commit();
    

    You can now add/attach a different fragment to R.id.activity_fragment_placeholder. Notice that I'm using hide() rather than replace(), that's the key difference that keeps the view from being destroyed. When you want the fragment back, you can use show() or Android will do this automatically when the user clicks "Back" if you use addToBackStack() when adding/attaching your other fragment.