title: Using FragmentStatePageAdapter to retain position for fragment with ViewPager
body: <p>I have an activity that contains a TabLayout and uses a fragment for each tab. In return, that fragment contains another fragment for use with ViewPager. This is my setup:</p>
  
  <p><strong>RoutineActivity.java</strong></p>
  
  <pre><code>public class RoutineActivity extends AppCompatActivity {
  private ArrayList&lt;CategoryFragment&gt; categories = new ArrayList&lt;&gt;();
  private TabLayout tabs;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_routine);
  
      // Set the toolbar as the action bar and add the Up button
      Toolbar toolbar = findViewById(R.id.routine_toolbar);
      setSupportActionBar(toolbar);
      getSupportActionBar().setDisplayHomeAsUpEnabled(true);
  
      // Get the intent and extract the string array
      Intent intent = getIntent();
      ArrayList&lt;String&gt; selected =
              intent.getStringArrayListExtra(SelectCategoriesActivity.EXTRA_CATEGORIES);
  
      // Set the TabLayout
      this.setTabs(selected);
  }
  
  // Set the tabs of the TabLayout given a list of tab names
  private void setTabs(ArrayList&lt;String&gt; tabs) {
      // Setup the tabs and create a fragment for each category
      this.tabs = findViewById(R.id.category_tabs);
      for (int x = 0; x &lt; tabs.size(); x++) {
          TabLayout.Tab tab = this.tabs.newTab().setText(tabs.get(x));
          // Select the first tab
          if (x == 0) {
              this.tabs.addTab(tab, true);
          } else {
              this.tabs.addTab(tab);
          }
  
          // Store the created fragment
          CategoryFragment categoryFragment = CategoryFragment.newInstance(tabs.get(x));
          this.categories.add(categoryFragment);
      }
  
      // Add the first fragment
      getSupportFragmentManager()
              .beginTransaction()
              .add(R.id.fragment_category_container, this.categories.get(0))
              .commit();
  
  
      // Add the tab selected listener
      this.tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
          @Override
          public void onTabSelected(TabLayout.Tab tab) {
              RoutineActivity.this.replaceFragment(tab.getPosition());
          }
  
          @Override
          public void onTabUnselected(TabLayout.Tab tab) {}
  
          @Override
          public void onTabReselected(TabLayout.Tab tab) {
  
          }
      });
  }
  
  // Replace the fragment corresponding to the category
  private void replaceFragment(int position) {
      FragmentManager fm = getSupportFragmentManager();
      FragmentTransaction ft = fm.beginTransaction();
      ft.replace(R.id.fragment_category_container, this.categories.get(position));
      ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
      ft.commit();
  } 
  }
  </code></pre>
  
  <p><strong>CategoryFragment.java</strong></p>
  
  <pre><code>public class CategoryFragment extends Fragment {
  private ViewPager pager;
  private ScreenSlidePagerAdapter pagerAdapter;
  
  public CategoryFragment() {} // Required empty public constructor
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
  
      ArrayList&lt;String&gt; selected = new ArrayList&lt;&gt;();
      selected.add("1 " + getArguments().get("CATEGORY"));
      selected.add("2 " + getArguments().get("CATEGORY"));
      selected.add("3 " + getArguments().get("CATEGORY"));
      selected.add("4 " + getArguments().get("CATEGORY"));
  
      // Instantiate the PageAdapter
      this.pagerAdapter = new ScreenSlidePagerAdapter(getChildFragmentManager(), selected);
  }
  
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                           Bundle savedInstanceState) {
      // Inflate the layout for this fragment
      View view = inflater.inflate(R.layout.fragment_category, container, false);
  
      // Instantiate ViewPager and set its adapter
      this.pager = view.findViewById(R.id.exercise_pager);
      this.pager.setAdapter(this.pagerAdapter);
  
      return view;
  }
  
  // Return a new instance of this fragment
  public static CategoryFragment newInstance(String category) {
      Bundle args = new Bundle();
      args.putString("CATEGORY", category);
  
      CategoryFragment categoryFragment = new CategoryFragment();
      categoryFragment.setArguments(args);
  
      return categoryFragment;
  }
  
  // The page adapter
  private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
  
      private ArrayList&lt;String&gt; selected;
  
      public ScreenSlidePagerAdapter(FragmentManager fm, ArrayList&lt;String&gt; data) {
          super(fm);
          this.selected = data;
      }
  
      @Override
      public Fragment getItem(int position) {
          return ExerciseFragment.newInstance(this.selected.get(position));
      }
  
      @Override
      public int getCount() {
          return this.selected.size();
      }
  }
  }
  </code></pre>
  
  <p><strong>ExerciseFragment.java</strong></p>
  
  <pre><code>public class ExerciseFragment extends Fragment {
  
  public ExerciseFragment() {} // Required empty public constructor
  
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                           Bundle savedInstanceState) {
      View rootView = inflater.inflate(
              R.layout.fragment_exercise_page, container, false);
  
      // Change the header to the category
      TextView tv = rootView.findViewById(R.id.textView_header);
      tv.setText(getArguments().getString("CAT"));
  
      return rootView;
  }
  
  public static ExerciseFragment newInstance(String category) {
      Bundle args = new Bundle();
      args.putString("CAT", category);
  
      ExerciseFragment exerciseFragment = new ExerciseFragment();
      exerciseFragment.setArguments(args);
  
      return exerciseFragment;
  }
  
  }
  </code></pre>
  
  <p>LogCat</p>
  
  <pre><code>java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.util.SparseArray.get(int)' on a null object reference
  at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:902)
  at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:216)
  at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1453)
  at android.view.View.dispatchRestoreInstanceState(View.java:16886)
  at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3470)
  at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3476)
  at android.view.View.restoreHierarchyState(View.java:16864)
  at android.support.v4.app.Fragment.restoreViewState(Fragment.java:500)
  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1445)
  at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740)
  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809)
  at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799)
  at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580)
  at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367)
  at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
  at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229)
  at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:700)
  at android.os.Handler.handleCallback(Handler.java:751)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:154)
  at android.app.ActivityThread.main(ActivityThread.java:6682)
  at java.lang.reflect.Method.invoke(Native Method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
  </code></pre>
  
  <p>The problem is that when I select a new tab, everything works fine, a new fragment is added, however when I go back to a previous tab, the whole app crashes. I think the problem is how the ViewPager is restoring the fragment but I have no clue how to fix it. I've replaced <code>FragmentStatePagerAdapter</code> to <code>FragmentPagerAdapter</code> and the problem goes away. However, I need to use the former since I will be using many pages (over 20). I just need the CategoryFragment to retain the fragment it left off on. Any ideas?</p>