我在一些Android代码中做了一些重构,我在一个直接连接到Activity的视图中使用FragmentPagerAdapter和ViewPager。然后,FragmentPageAdapter从Activity移动到separat Fragment(现在是该活动的子代),作为重构的一部分。
这种变化并不顺利。例如,在方向更改后,缓存的选项卡会消失。 NullPointerExceptions在我的Fragment子类中被抛出,因为findViewById无法找到它的View组件(看起来像片段的View层次结构在旋转更改后以某种方式被破坏)。
我使用的是最新版本的Android支持库。
出了什么问题?
编辑:
我目前的实施:
public class TabsPageAdapter extends FragmentPagerAdapter {
...
@Override
public Fragment getItem(int index) {
// tabs = list of Fragment instances created in contructor of pager adapter - bad habbit?
return tabs.get(index).getTabFragment();
}
...
}
public class StatsFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.stats_view, container, false);
TabsPageAdapter adapter = new TabsPageAdapter(getActivity().getSupportFragmentManager(), getActivity());
ViewPager viewPager = (ViewPager) root.findViewById(R.id.tabPager);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(3);
TabPageIndicator pageIndicator = (TabPageIndicator) root.findViewById(R.id.tabIndicator);
pageIndicator.setViewPager(viewPager);
return root;
}
}
public class MedalsTab extends Fragment {
private MedalAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.medals, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
this.adapter = new MedalAdapter();
GridView gridView = (GridView) getActivity().findViewById(R.id.grdMedals);
// Nullpointerexception is thrown here
gridView.setAdapter(adapter);
}
@Override
public void onSaveInstanceState(Bundle outState) {
//first saving my state, so the bundle wont be empty.
//http://code.google.com/p/android/issues/detail?id=19917
outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE");
super.onSaveInstanceState(outState);
}
...
}
我在浏览寻呼机适配器的标签时也遇到此异常。
E/AndroidRuntime(28706): java.lang.NullPointerException
E/AndroidRuntime(28706): at android.support.v4.app.Fragment.instantiate(Fragment.java:391)
答案 0 :(得分:7)
以下是我解决问题的方法:
我更改了getItem方法来构造并返回一个新实例(感谢Luksprog):
@Override
public Fragment getItem(int index) {
return tabs.get(index).constructFragment();
}
我们需要使用getChildFragmentManger()
而不是getActivity().getFragmentManager()
返回的FragmentManager来创建片段,因为ViewPager驻留在片段中:
TabsPageAdapter adapter = new TabsPageAdapter(getChildFragmentManager(), getActivity());
答案 1 :(得分:4)
// tabs =在寻呼机的构造函数中创建的Fragment实例列表 适配器 - 糟糕的habbit?
是的,这很糟糕,可能是轮换后问题的根源。当ViewPager
需要在页面中显示时,getItem
将使用ViewPager
方法来获取片段。轮换后,getItem
将检查其状态并查看以前有多少个碎片,并在没有getItem()
方法的情况下手动恢复它们。如果您在此机制之外保留片段,则需要更改适配器以使其仅使用列表中的片段(ViewPager
是不够的),或者更新片段列表以仅引用由此创建或重新创建的片段。 ViewPager
。您很可能不会这样做,并且在轮换之后,您尝试访问列表片段,假设它们是来自NullPointerException
的行为,它会抛出GridView
。
GridView gridView =(GridView) 。getActivity()findViewById(R.id.grdMedals);
如果Fragment
位于getView().findViewById...
的布局中,请通过{{1}}访问。