title: how to save listview items/adapter in fragment and restore from back stack
body: <p>I've been tried to search about this problem but I couldn't get any solution.
  I've got a problem about saving ListView items in fragment. The case is I have several fragments </p>
  
  <blockquote>
    <p>let say FRAGMENT A, FRAGMENT B and FRAGMENT C, and FRAGMENT A has a
    listview, the item of the listview can be changed when user scroll
    (just like timeline in social media apps). When I change the fragment
    A, I used addToBackStack(null) method.</p>
  </blockquote>
  
  <p>The problem is, how to save the listview and restore its if back button is pressed?</p>
  
  <blockquote>
    <p>onSaveInstanceState() is never called because the Activity host is never killed, only change the fragment using this:</p>
  </blockquote>
  
  <pre><code>public void changeFragment(Fragment fragment, ColorDrawable colorDrawable){
      Fragment newFrag = fragment;
      ColorDrawable newColor = colorDrawable;
  
      String backStateName = fragment.getClass().getName();
      FragmentManager manager = getSupportFragmentManager();
      boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
      if (!fragmentPopped){ //fragment not in back stack, create it.
          FragmentTransaction ft = manager.beginTransaction();
          ft.replace(R.id.content_fragment, fragment);
          ft.addToBackStack(backStateName);
          ft.commit();
      }
  
      //to change the actionbar color
      getSupportActionBar().setBackgroundDrawable(newColor);
  }
  </code></pre>
  
  <p>here is my code trying to save and restore the listview:</p>
  
  <pre><code>    @Override
      public void onDestroyView() {
          super.onDestroyView();
          //try to save listview scroll
          index = myList.getFirstVisiblePosition();
          View v = myList.getChildAt(0);
          top = (v == null) ? 0 : (v.getTop() - myList.getPaddingTop());
          index = 1;
          //try to save listview items
          savedAdapter = adapter;
          fromBackStack = true;
      }
  
      @Override
      public void onActivityCreated(Bundle savedInstanceState) {
          super.onActivityCreated(savedInstanceState);
  
          myList.setSelectionFromTop(index, top);
          myList.setAdapter(savedAdapter);
      }
  </code></pre>
  
  <p>here the code I've done so far :</p>
  
  <pre><code>    package com.ngapainya.ngapainya.fragment;
  
  
  import android.app.Activity;
  import android.graphics.drawable.ColorDrawable;
  import android.net.ParseException;
  import android.os.AsyncTask;
  import android.os.Bundle;
  import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentActivity;
  import android.support.v4.widget.SwipeRefreshLayout;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.AbsListView;
  import android.widget.AdapterView;
  import android.widget.ListView;
  
  import com.ngapainya.ngapainya.R;
  import com.ngapainya.ngapainya.activity.volunteer.ContainerActivity;
  import com.ngapainya.ngapainya.adapter.HomeAdapter;
  import com.ngapainya.ngapainya.fragment.child.DetailPostFragment;
  import com.ngapainya.ngapainya.model.Home;
  
  import java.util.ArrayList;
  
  /**
   * A simple {@link Fragment} subclass.
   */
  public class HomeFragment extends Fragment implements AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener{
      private FragmentActivity myContext;
      private View myFragmentView;
      private ArrayList&lt;Home&gt; filelist;
      private ListView myList;
      private HomeAdapter adapter;
      private SwipeRefreshLayout swipeRefreshLayout;
  
      //try save instance listview
      boolean fromBackStack = false;
      int index;
      int top;
      HomeAdapter savedAdapter;
  
      @Override
      public void onDestroyView() {
          super.onDestroyView();
          //try to save listview scroll
          index = myList.getFirstVisiblePosition();
          View v = myList.getChildAt(0);
          top = (v == null) ? 0 : (v.getTop() - myList.getPaddingTop());
          index = 1;
          //try to save listview items
          savedAdapter = adapter;
          fromBackStack = true;
      }
  
      @Override
      public void onActivityCreated(Bundle savedInstanceState) {
          super.onActivityCreated(savedInstanceState);
  
          myList.setSelectionFromTop(index, top);
          myList.setAdapter(savedAdapter);
      }
  
      @Override
      public void onAttach(Activity activity) {
          myContext = (FragmentActivity) activity;
          super.onAttach(activity);
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
                               Bundle savedInstanceState) {
          // Inflate the layout for this fragment
          myFragmentView = inflater.inflate(R.layout.fragment_home, container, false);
  
          filelist = new ArrayList&lt;Home&gt;();
  
          //dummy data
          filelist.add(new Home("post", 1)); //post image
          filelist.add(new Home("post", 2)); //post location
          filelist.add(new Home("post", 3)); //post url
          filelist.add(new Home("post", 4)); //become friend with
          filelist.add(new Home("post", 0)); //post status
  
          swipeRefreshLayout = (SwipeRefreshLayout) myFragmentView.findViewById(R.id.swipe_refresh_layout);
          swipeRefreshLayout.setOnRefreshListener(this);
          /**
           * Showing Swipe Refresh animation on activity create
           * As animation won't start on onCreate, post runnable is used
           */
          swipeRefreshLayout.post(new Runnable() {
                                      @Override
                                      public void run() {
                                          swipeRefreshLayout.setRefreshing(true);
                                          //do something
                                          swipeRefreshLayout.setRefreshing(false);
                                      }
                                  }
          );
  
          myList = (ListView) myFragmentView.findViewById(R.id.list_home);
          //myList.setAdapter(new HomeAdapter(myContext, filelist));
          adapter = new HomeAdapter(myContext, filelist);
          myList.setOnItemClickListener(this);
  
          if(!fromBackStack) {
              new RemoteDataTask().execute();
          }
  
          return myFragmentView;
      }
  
      /**
       * This method is called when swipe refresh is pulled down
       */
      @Override
      public void onRefresh() {
          //do something
          myList.setAdapter(adapter);
          ArrayList&lt;Home&gt; new_filelist = new ArrayList&lt;&gt;();
          new_filelist.add(new Home("Post", 4));
  
          filelist.addAll(0, new_filelist);
          adapter.notifyDataSetChanged();
          swipeRefreshLayout.setRefreshing(false);
      }
  
      @Override
      public void onItemClick(AdapterView&lt;?&gt; parent, View view, int position, long id) {
          Home tmp = (Home) parent.getItemAtPosition(position);
          DetailPostFragment detailPostFragment = new DetailPostFragment();
          Bundle args = new Bundle();
          switch (tmp.type) {
              case 0:
                  args.putInt("postType", tmp.type);
                  detailPostFragment.setArguments(args);
                  ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                  break;
              case 1:
                  args.putInt("postType", tmp.type);
                  detailPostFragment.setArguments(args);
                  ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                  break;
              case 2:
                  args.putInt("postType", tmp.type);
                  detailPostFragment.setArguments(args);
                  ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                  break;
              case 3:
                  args.putInt("postType", tmp.type);
                  detailPostFragment.setArguments(args);
                  ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                  break;
              case 4:
                  args.putInt("postType", tmp.type);
                  detailPostFragment.setArguments(args);
                  ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                  break;
          }
      }
  
      private class RemoteDataTask extends AsyncTask&lt;String, Void, ArrayList&lt;Home&gt;&gt; {
  
          @Override
          protected void onPreExecute() {
              super.onPreExecute();
          }
  
          @Override
          protected ArrayList&lt;Home&gt; doInBackground(String... urls) {
              try {
                  ArrayList&lt;Home&gt; new_filelist = new ArrayList&lt;Home&gt;();
                  new_filelist.add(new Home("post", 3)); //post url
                  new_filelist.add(new Home("post", 4)); //become friend with
                  new_filelist.add(new Home("post", 0)); //post status
                  filelist.addAll(new_filelist);
              } catch (ParseException e) {
                  Log.e("Error", e.getMessage());
                  e.printStackTrace();
              }
              return filelist;
          }
  
          @Override
          protected void onPostExecute(ArrayList&lt;Home&gt; organization) {
              myList.setAdapter(new HomeAdapter(myContext, filelist));
              // Create an OnScrollListener
              myList.setOnScrollListener(new AbsListView.OnScrollListener() {
  
                  @Override
                  public void onScrollStateChanged(AbsListView view,
                                                   int scrollState) { // TODO Auto-generated method stub
                      int threshold = 1;
                      int count = myList.getCount();
  
                      if (scrollState == SCROLL_STATE_IDLE) {
                          if (myList.getLastVisiblePosition() &gt;= count
                                  - threshold) {
                              // Execute LoadMoreDataTask AsyncTask
                              new LoadMoreDataTask().execute();
                          }
                      }
                  }
  
                  @Override
                  public void onScroll(AbsListView view, int firstVisibleItem,
                                       int visibleItemCount, int totalItemCount) {
                      // TODO Auto-generated method stub
  
                  }
  
              });
          }
      }
  
      public class LoadMoreDataTask extends AsyncTask&lt;String, Void, ArrayList&lt;Home&gt;&gt; {
  
          @Override
          protected void onPreExecute() {
              super.onPreExecute();
          }
  
          @Override
          protected ArrayList&lt;Home&gt; doInBackground(String... urls) {
              try {
                  // web service request
                  ArrayList&lt;Home&gt; new_filelist = new ArrayList&lt;Home&gt;();
                  new_filelist.add(new Home("post", 0)); //post status
                  if(new_filelist  != null &amp;&amp; new_filelist.size() &gt; 0 ){
                      filelist.addAll(new_filelist);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return filelist;
          }
  
          @Override
          protected void onPostExecute(ArrayList&lt;Home&gt; organization) {
              int position = myList.getLastVisiblePosition();
              adapter = new HomeAdapter(myContext, filelist);
              myList.setAdapter(adapter);
              adapter.notifyDataSetChanged();
              myList.setSelectionFromTop(position, 0);
          }
      }
  
  }
  </code></pre>
  
  <p>I hope someone could help me out, thank you .</p>
  
  <blockquote>
    <p>Updated Code
    This is my code so far, it works when I try to saved the listview items and its adapter, perhaps this is a bit tricky. If someone has any idea would be appreciated.</p>
  </blockquote>
  
  <pre><code>package com.ngapainya.ngapainya.fragment;
  import android.app.Activity;
  import android.graphics.drawable.ColorDrawable;
  import android.net.ParseException;
  import android.os.AsyncTask;
  import android.os.Bundle;
  import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentActivity;
  import android.support.v4.widget.SwipeRefreshLayout;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.AbsListView;
  import android.widget.AdapterView;
  import android.widget.ListView;
  
  import com.ngapainya.ngapainya.R;
  import com.ngapainya.ngapainya.activity.volunteer.ContainerActivity;
  import com.ngapainya.ngapainya.adapter.HomeAdapter;
  import com.ngapainya.ngapainya.fragment.child.DetailPostFragment;
  import com.ngapainya.ngapainya.model.Home;
  
  import java.util.ArrayList;
  
  /**
   * A simple {@link Fragment} subclass.
   */
  public class HomeFragment extends Fragment implements AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener{
      private FragmentActivity myContext;
      private View myFragmentView;
      private ArrayList&lt;Home&gt; filelist;
      private ListView myList;
      private HomeAdapter adapter;
      private SwipeRefreshLayout swipeRefreshLayout;
  
      /*
      * these variables used to restore the listview
      * when calling the fragment from backstack
      * */
      private boolean fromBackStack = false;
      private HomeAdapter savedAdapter;
      private ArrayList&lt;Home&gt; savedFilelist;
  
      @Override
      public void onDestroyView() {
          super.onDestroyView();
          savedAdapter = adapter;
          savedFilelist = filelist;
          fromBackStack = true;
          Log.e("onDestroyView", "onDestroyView");
      }
  
      @Override
      public void onAttach(Activity activity) {
          myContext = (FragmentActivity) activity;
          super.onAttach(activity);
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
                               Bundle savedInstanceState) {
          // Inflate the layout for this fragment
          myFragmentView = inflater.inflate(R.layout.fragment_home, container, false);
  
          Log.e("onCreateView", "onCreateView");
  
          swipeRefreshLayout = (SwipeRefreshLayout) myFragmentView.findViewById(R.id.swipe_refresh_layout);
          swipeRefreshLayout.setOnRefreshListener(this);
          /**
           * Showing Swipe Refresh animation on activity create
           * As animation won't start on onCreate, post runnable is used
           */
          /*swipeRefreshLayout.post(new Runnable() {
                                      @Override
                                      public void run() {
                                          swipeRefreshLayout.setRefreshing(true);
                                          //do something
                                          swipeRefreshLayout.setRefreshing(false);
                                      }
                                  }
          );*/
  
          myList = (ListView) myFragmentView.findViewById(R.id.list_home);
          //myList.setAdapter(new HomeAdapter(myContext, filelist));
  
          myList.setOnItemClickListener(this);
  
          filelist = new ArrayList&lt;Home&gt;();
          adapter = new HomeAdapter(myContext, filelist);
  
          if(fromBackStack) {
              filelist = savedFilelist;
              adapter = savedAdapter;
          }
  
          new RemoteDataTask().execute();
          return myFragmentView;
      }
  
      /**
       * This method is called when swipe refresh is pulled down
       */
      @Override
      public void onRefresh() {
          ArrayList&lt;Home&gt; new_filelist = new ArrayList&lt;&gt;();
          new_filelist.add(new Home("Post", 4));
  
          filelist.addAll(0, new_filelist);
          adapter.notifyDataSetChanged();
          swipeRefreshLayout.setRefreshing(false);
  
          Log.e("onRefresh", "onRefresh");
      }
  
      /*
      * This method is called whenever the listview item is clicked
      * */
  
      @Override
      public void onItemClick(AdapterView&lt;?&gt; parent, View view, int position, long id) {
          Home tmp = (Home) parent.getItemAtPosition(position);
          DetailPostFragment detailPostFragment = new DetailPostFragment();
          Bundle args = new Bundle();
          switch (tmp.type) {
              case 0:
                  args.putInt("postType", tmp.type);
                  detailPostFragment.setArguments(args);
                  ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                  break;
              case 1:
                  args.putInt("postType", tmp.type);
                  detailPostFragment.setArguments(args);
                  ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                  break;
              case 2:
                  args.putInt("postType", tmp.type);
                  detailPostFragment.setArguments(args);
                  ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                  break;
              case 3:
                  args.putInt("postType", tmp.type);
                  detailPostFragment.setArguments(args);
                  ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                  break;
              case 4:
                  args.putInt("postType", tmp.type);
                  detailPostFragment.setArguments(args);
                  ((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
                  break;
          }
      }
  
      /*
      * This method is called in onCreateView method
      * Used to load data from server and populate them into
      * the listview
      * */
  
      private class RemoteDataTask extends AsyncTask&lt;String, Void, ArrayList&lt;Home&gt;&gt; {
  
          @Override
          protected void onPreExecute() {
              super.onPreExecute();
          }
  
          @Override
          protected ArrayList&lt;Home&gt; doInBackground(String... urls) {
              try {
                  ArrayList&lt;Home&gt; new_filelist = new ArrayList&lt;Home&gt;();
                  //dummy data
                  new_filelist.add(new Home("post", 1)); //post image
                  new_filelist.add(new Home("post", 2)); //post location
                  new_filelist.add(new Home("post", 3)); //post url
                  new_filelist.add(new Home("post", 4)); //become friend with
                  new_filelist.add(new Home("post", 0)); //post status
                  new_filelist.add(new Home("post", 3)); //post url
                  new_filelist.add(new Home("post", 4)); //become friend with
                  new_filelist.add(new Home("post", 0)); //post status
                  filelist.addAll(new_filelist);
              } catch (ParseException e) {
                  Log.e("Error", e.getMessage());
                  e.printStackTrace();
              }
              return filelist;
          }
  
          @Override
          protected void onPostExecute(ArrayList&lt;Home&gt; organization) {
              myList.setAdapter(adapter);
              // Create an OnScrollListener
              myList.setOnScrollListener(new AbsListView.OnScrollListener() {
  
                  @Override
                  public void onScrollStateChanged(AbsListView view,
                                                   int scrollState) { // TODO Auto-generated method stub
                      int threshold = 1;
                      int count = myList.getCount();
  
                      if (scrollState == SCROLL_STATE_IDLE) {
                          if (myList.getLastVisiblePosition() &gt;= count
                                  - threshold) {
                              // Execute LoadMoreDataTask AsyncTask
                              new LoadMoreDataTask().execute();
                          }
                      }
                  }
  
                  @Override
                  public void onScroll(AbsListView view, int firstVisibleItem,
                                       int visibleItemCount, int totalItemCount) {
                      // TODO Auto-generated method stub
  
                  }
  
              });
          }
      }
  
      /*
      * This method is called when the listview pulled down
      * it will trigger this method to load more items from server
      * */
  
      public class LoadMoreDataTask extends AsyncTask&lt;String, Void, ArrayList&lt;Home&gt;&gt; {
  
          @Override
          protected void onPreExecute() {
              super.onPreExecute();
          }
  
          @Override
          protected ArrayList&lt;Home&gt; doInBackground(String... urls) {
              try {
                  // web service request
                  ArrayList&lt;Home&gt; new_filelist = new ArrayList&lt;Home&gt;();
                  new_filelist.add(new Home("post", 0)); //post status
                  new_filelist.add(new Home("post", 1));
                  if(new_filelist  != null &amp;&amp; new_filelist.size() &gt; 0 ){
                      filelist.addAll(new_filelist);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return filelist;
          }
  
          @Override
          protected void onPostExecute(ArrayList&lt;Home&gt; organization) {
              int position = myList.getLastVisiblePosition();
              //adapter = new HomeAdapter(myContext, filelist);
              myList.setAdapter(adapter);
              adapter.notifyDataSetChanged();
              myList.setSelectionFromTop(position, 0);
          }
      }
  
  }
  </code></pre>