2

我在一些Android代码中进行了一些重构,其中我将FragmentPagerAdapter与ViewPager一起使用,直接连接到Activity。然后,将FragmentPageAdapter从Activity移动到单独片段(现在是该活动的子节点),作为重构的一部分。在片段中使用FragmentPagerAdapter

这个改变并不顺利。例如,缓存的标签在方向更改后会消失。 NullPointerExceptions在我的Fragment子类中的所有地方被抛出,因为findViewById无法找到它的View组件(看起来像Fragments的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

我附上当前代码 – bjorncs 2013-03-04 08:20:19

回答

5

这里是我解决了这个问题:

我改变了的getItem方法构造并返回一个新的实例(感谢Luksprog):

@Override 
    public Fragment getItem(int index) { 
     return tabs.get(index).constructFragment(); 
    } 

我们需要使用getChildFragmentManger()返回的FragmentManager而不是getActivity().getFragmentManager()来创建碎片,因为ViewPager驻留在一个碎片中:

TabsPageAdapter adapter = new TabsPageAdapter(getChildFragmentManager(), getActivity()); 
+1

您的回答“我们需要使用由getChildFragmentManger()返回的FragmentManager而不是getActivity()。getFragmentManager()创建片段,因为ViewPager驻留在片段中”完全解决了我的问题。并且没有人知道这一点。谢谢您! – 2013-11-15 14:43:05

4

//标签=在寻呼机 适配器的构造器创建片断实例的列表 - 坏习惯中?

是的,这是很糟糕的,可能是你的问题在旋转后的来源。 ViewPager将使用getItem方法在需要它们显示在页面中时获取片段。旋转后,ViewPager将检查其状态,并查看它以前有多少片段,并在没有使用getItem方法的情况下手动恢复它们。如果在此机制外部持有碎片,则您需要更改适配器,使其仅使用列表中的碎片(getItem()不够),或者更新碎片列表以仅引用由ViewPager创建或重新创建的碎片。您很可能不会这样做,并且在轮换之后,您尝试访问列表片段(假设它们是ViewPager中的那个),该操作将抛出NullPointerException

GridView gridView =(GridView) getActivity()。findViewById(R.id.grdMedals);

如果该GridView是在Fragment的布局,请通过getView().findViewById...访问它。

+0

谢谢,它解决了所有的崩溃问题。尽管导航出StatsFragment然后再返回,但ViewPager仍然丢失它的缓存标签片段。 – bjorncs 2013-03-04 22:14:38

+0

@bjorncs你应该用新的代码发布一个新问题,并且通过失去缓存的标签片断来解释你究竟是什么意思。 – Luksprog 2013-03-05 06:31:22

+0

Nvm,将子片段管理器传递给ViewPagerAdapter修复了问题。 – bjorncs 2013-03-06 00:07:50

相关问题