片段 ViewPager NullPointer 问题

Fragment ViewPager NullPointer issue

我有一些片段正在交换进出我的主 activity。初始片段称为 BrowseHomeFragment 并且最初加载正常,但是当我用新片段替换它然后将其替换回来时,我收到以下错误

java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
    at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:686)
    at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:215)
    at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:536)

BrowseHomeFragment 的 onCreateView 方法:

public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
        InjectionGraph.inject(this);

        View view = inflater.inflate(R.layout.fragment_browse, container, false);
        ButterKnife.inject(this, view);

        addTabsToPagerSlidingTabStrip(inflater);

        viewPager.setAdapter(new BrowseHomePagerAdapter(getChildFragmentManager()));

        pagerSlidingTabStrip.setViewPager(viewPager);
        // has to set page change listener in indicator
        pagerSlidingTabStrip.setOnPageChangeListener(pageChangeListener);

        viewPager.setCurrentItem(initialTabIndex);

        return view;
    }

BrowseHomePagerAdapter

public class BrowseHomePagerAdapter extends FragmentStatePagerAdapter {
    private int lastPosition = -1;

    @Inject
    BrowseHomepageMetricRecorder browseHomepageMetricRecorder;

    @Inject
    NetworkMonitor networkMonitor;


    /**
     * For explanation on why Fragment references are cached, please refer to
     * 
     */
    final SparseArray<Fragment> registeredFragments = new SparseArray<>();


    public BrowseHomePagerAdapter(FragmentManager fm) {
        super(fm);
        InjectionGraph.inject(this);

    }


    @Override
    public Fragment getItem(int i) {

        switch (BrowseHomeFragment.Tab.resolve(i)) {
        // TODO: connect category, favorite, and downloaded list fragments
        case Categories:
            return new CategoryHomePageFragment();
        case Downloaded:
            return new OfflineContentFragment();
        default:
            return new ComingSoonFragment();
        }
    }


    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }


    @Override
    public int getCount() {
        return BrowseHomeFragment.Tab.values().length;
    }


    @Override
    public CharSequence getPageTitle(int position) {
        return BrowseHomeFragment.Tab.resolve(position).name();
    }


    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        if (position != lastPosition) { // debounce Android's redundant calls
            switch (BrowseHomeFragment.Tab.resolve(position)) {
                case Categories:
                    browseHomepageMetricRecorder.recordGotoCategoriesMetric();
                    if (!networkMonitor.isDeviceConnected()) {
                        networkMonitor.postUserActionRequiresConnectivityEvent();
                    }
                    break;
                case Downloaded:
                    browseHomepageMetricRecorder.recordGotoDownloadedMetric();
                    break;
                default:
                    break;
            }
            lastPosition = position;
        }

        super.setPrimaryItem(container, position, object);
    }


    public Object instantiateItem(ViewGroup container, int position) {
        final Fragment fragment = (Fragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }


    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }


    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }

虽然我有 运行 调试并且它不为空,但我发现 viewPager 丢失了一些东西..

我可以通过在每次用 BrowseFragment 替换活动片段之前简单地重新创建 BrowseFragment 来解决这个问题,但我宁愿能够重用它。

如果能帮助理解究竟发生了什么以及如何解决它,我们将不胜感激。

苦思冥想之后,我找到了解决办法。在我的适配器中,我现在重写了 onRestoreState 什么也不做。

@Override
public void restoreState(Parcelable state, ClassLoader loader) {
     //Do NOTHING;
}

我不确定这是否是最好的解决方案,似乎没有任何不良影响,如果有人可以谈谈这个 "fix" 以及它为什么有效或提供更好的解决方案,那将是非常感谢。