片段 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" 以及它为什么有效或提供更好的解决方案,那将是非常感谢。
我有一些片段正在交换进出我的主 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" 以及它为什么有效或提供更好的解决方案,那将是非常感谢。