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

相關問題