Search code examples
androidandroid-fragmentsandroid-activityandroid-fragmentactivity

Retain fragment data on screen rotation


I have 3 fragments where 1 fragment makes changes to the other 2.

The problem is: When I rotate the screen background color and places of fragments 2 and 3 are restored. I want to keep them without modifying AndroidManifest.xml. Is it best to use onSaveInstanceState or setRetainInstance or both?

I found some other answers about retaining fragments but none of them were beneficial for my case.

FirstFragment

public class FirstFragment extends Fragment 
{
    private OnFragmentInteractionListener mListener;
    private ChangeColorListener mCallBack;
    private boolean clickCheck = false;

    public FirstFragment() { }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_first, container, false);

        Button buttonOk = v.findViewById(R.id.button_ok);
        Button btn = v.findViewById(R.id.button_replace);
        buttonOk.setOnClickListener(v1 -> mCallBack.changeColor(R.color.black));
        btn.setOnClickListener(v12 -> {
            clickCheck = !clickCheck;
            mListener.changeFragment(clickCheck);
        });

        return v;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        
        if (savedInstanceState!=null) {
            mCallBack =(MainActivity)getActivity();
            mListener = (MainActivity)getActivity();
        }
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);

        if (context instanceof ChangeColorListener) {
            mCallBack = (ChangeColorListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement ChangeColorListener");
        }

        try {
            mListener = (OnFragmentInteractionListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }


    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }
}

SecondFragment

public class SecondFragment extends Fragment 
{
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_second, container, false);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }
    public void change(int color){
        getView().setBackgroundColor(color);
    }
}

ThirdFragment

public class ThirdFragment extends Fragment {


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

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);

    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

    public void change(int color){
        getView().setBackgroundColor(color);
    }
}

Solution

  • setRetainInstance() is deprecated. ViewModel is recommended for retaining data across configuration changes.