I have an Activity in which I go through several fragments. In every fragment I have several views (EditText, ListView, Map, etc).

How can I save the instance of the fragment that is shown at that moment? I need it to work when the activity is onPause() --> onResume(). Also I need it to work when I return from another fragment (pop from backstack).

From the main Activity I call the first fragment, then from the the fragment I call the next one.

Code for my Activity:

public class Activity_Main extends FragmentActivity{

public static Fragment_1 fragment_1;
public static Fragment_2 fragment_2;
public static Fragment_3 fragment_3;
public static FragmentManager fragmentManager;

@Override
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

     fragment_1 = new Fragment_1();

     fragment_2 = new Fragment_2();

     fragment_3 = new Fragment_3();

     fragmentManager = getSupportFragmentManager();
     FragmentTransaction transaction_1 = fragmentManager.beginTransaction();
     transaction_1.replace(R.id.content_frame, fragment_1);
     transaction_1.commit();
}}

Then here is the code for one of my fragments:

public class Fragment_1 extends Fragment {

      private EditText title;
      private Button go_next;


      @Override
      public View onCreateView(final LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_1,
            container, false);

            title = (EditText) rootView.findViewById(R.id.title);

            go_next = (Button) rootView.findViewById(R.id.go_next);

            image.setOnClickListener(new View.OnClickListener() {

         @Override
         public void onClick(View v) {

                 FragmentTransaction transaction_2 = Activity_Main.fragmentManager
                .beginTransaction();

                 transaction_2.replace(R.id.content_frame,
                  Activity_Main.fragment_2);
                 transaction_2.addToBackStack(null);
                 transaction_2.commit();  

            });
        }}

I have searched a lot of information but nothing clear. Can somebody give a clear solution and an example, please ?


Solution 1:

When a fragment is moved to the backstack, it isn't destroyed. All the instance variables remain there. So this is the place to save your data. In onActivityCreated you check the following conditions:

  1. Is the bundle != null? If yes, that's where the data is saved (probably orientation change).
  2. Is there data saved in instance variables? If yes, restore your state from them (or maybe do nothing, because everything is as it should be).
  3. Otherwise your fragment is shown for the first time, create everything anew.

Edit: Here's an example

public class ExampleFragment extends Fragment {
    private List<String> myData;

    @Override
    public void onSaveInstanceState(final Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable("list", (Serializable) myData);
    }

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

        if (savedInstanceState != null) {
            //probably orientation change
            myData = (List<String>) savedInstanceState.getSerializable("list");
        } else {
            if (myData != null) {
                //returning from backstack, data is fine, do nothing
            } else {
                //newly created, compute data
                myData = computeData();
            }
        }
    }
}

Solution 2:

Android fragment has some advantages and some disadvantages. The most disadvantage of the fragment is that when you want to use a fragment you create it ones. When you use it, onCreateView of the fragment is called for each time. If you want to keep state of the components in the fragment you must save fragment state and yout must load its state in the next shown. This make fragment view a bit slow and weird.

I have found a solution and I have used this solution: "Everything is great. Every body can try".

When first time onCreateView is being run, create view as a global variable. When second time you call this fragment onCreateView is called again you can return this global view. The fragment component state will be kept.

View view;

@Override
public View onCreateView(LayoutInflater inflater,
        @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    setActionBar(null);
    if (view != null) {
        if ((ViewGroup)view.getParent() != null)
            ((ViewGroup)view.getParent()).removeView(view);
        return view; 
    }
    view = inflater.inflate(R.layout.mylayout, container, false);
}