Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用FragmentStatePageAdapter在ViewPager中保留片段的位置_Java_Android_Android Fragments_Android Viewpager_Fragmentstatepageradapter - Fatal编程技术网

Java 使用FragmentStatePageAdapter在ViewPager中保留片段的位置

Java 使用FragmentStatePageAdapter在ViewPager中保留片段的位置,java,android,android-fragments,android-viewpager,fragmentstatepageradapter,Java,Android,Android Fragments,Android Viewpager,Fragmentstatepageradapter,我有一个活动,它包含一个TabLayout,并为每个选项卡使用一个片段。作为回报,该片段包含另一个用于ViewPager的片段。这是我的设置: RoutineActivity.java public class RoutineActivity extends AppCompatActivity { private ArrayList<CategoryFragment> categories = new ArrayList<>(); private TabLayout ta

我有一个活动,它包含一个TabLayout,并为每个选项卡使用一个片段。作为回报,该片段包含另一个用于ViewPager的片段。这是我的设置:

RoutineActivity.java

public class RoutineActivity extends AppCompatActivity {
private ArrayList<CategoryFragment> categories = new ArrayList<>();
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<String> 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<String> tabs) {
    // Setup the tabs and create a fragment for each category
    this.tabs = findViewById(R.id.category_tabs);
    for (int x = 0; x < 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();
} 
}
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<String> selected = new ArrayList<>();
    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<String> selected;

    public ScreenSlidePagerAdapter(FragmentManager fm, ArrayList<String> 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();
    }
}
}
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;
}

}
LogCat

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)

问题是,当我选择一个新选项卡时,一切正常,添加了一个新片段,但是当我返回到以前的选项卡时,整个应用程序崩溃。我认为问题在于ViewPager如何恢复片段,但我不知道如何修复它。我已将
FragmentStatePagerAdapter
替换为
FragmentPagerAdapter
,问题消失了。但是,我需要使用前者,因为我将使用许多页面(超过20页)。我只需要CategoryFragment来保留它留下的片段。有什么想法吗?

我在SupportFragmentManager中发现了问题,当您向后移动时,mActive fragment数组的第一个元素为null,这将产生NullPointerException

我不知道为什么,但通过添加
ft.addToBackStack(null)在提交之前,问题消失了

然后,该方法保持为:

// Replace the fragment corresponding to the category
    private void replaceFragment(int position) {
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.fragment_category_container, this.categories.get(position));
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.addToBackStack(null);
        ft.commit();
    }

你能添加creash的堆栈跟踪吗?@Juan我已经添加了错误的日志。谢谢你,我做到了这一点,但我切换到使用ViewPager设置表格布局。这解决了这个问题,但实际上发生的是,backbackback会堆积起来。若您在fragmnet的onResume(或任何生命周期方法)中有服务器调用或任何代码,它将多次调用它!