35

當前,使用FragmentActivity,我使用以下代碼在2種片段之間切換。FragmentPagerAdapter getItem未被觸發

private void toggle() { 
    Fragment oldFragment = getSupportFragmentManager().findFragmentById(R.id.content); 
    Fragment fragment = null; 
    if (oldFragment instanceof ColorFragment) { 
     fragment = new ViewPagerFragment(); 
    } else { 
     fragment = new ColorFragment(android.R.color.black); 
    } 

    getSupportFragmentManager().beginTransaction().replace(R.id.content, fragment).commitAllowingStateLoss(); 
} 

2片段正在切換。

  • ColorFragment - 一個簡單的片段,用純黑色填充背景。
  • ViewPagerFragment - 片段包含ViewPager。用戶可以在紫色片段和藍色片段之間滑動。

負責划動紫色和藍色碎片的代碼如下。

private static class MyFragmentPagerAdapter extends FragmentPagerAdapter { 

    public MyFragmentPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public int getCount() { 
     return 2; 
    } 

    @Override 
    public Fragment getItem(int position) { 
     switch (position) { 
     case 0: 
      return new ColorFragment(android.R.color.holo_purple); 
     default: 
      return new ColorFragment(android.R.color.holo_blue_bright); 
     } 
    }  
} 

但是,我在切換過程中遇到了奇怪的行爲。

  1. 顯示黑色片段。
  2. 切換。
  3. 查看傳呼機,它可以在顯示的紫色和藍色碎片之間滑動。
  4. 切換。
  5. 顯示黑色片段。
  6. 切換。
  7. 沒有顯示,因爲MyFragmentPagerAdapter的getItem沒有被觸發。

我覺得我的情況是類似FragmentPagerAdapter getItem is not called

然而,頁面之間切換時,我不喜歡使用FragmentStatePagerAdapter,因爲潛在更大的開銷成本。

解決此問題的任何解決方法?

我有一個完整的可行的源代碼來說明此問題:https://www.dropbox.com/s/jok9tz5ktvfcteo/viewpagerbug.zip

+0

*我不喜歡使用FragmentStatePagerAdapter * - 嗯,你是否至少試圖看看它是否有任何分歧? *因爲在頁面之間切換時潛在的更多開銷的成本。* - 可能的開銷是多少?你用兩個片段發佈的場景很簡單。 – Luksprog 2013-03-23 14:59:37

+0

@Luksprog 2個紫色和藍色的顏色片段用於演示目的。真實案例片段比這更復雜。我知道我可以通過捆綁保存信息或保留實例片段技術來減少某些開銷的擴展。然而,我認識到避免我的情況開銷的最好方法是避免使用FragmentStatePagerAdapter。 – 2013-03-23 15:30:32

回答

101

任何變通方法來解決這個問題?

我已經下載了你的代碼,出現這個問題,因爲你沒有處理那些Fragments的權利。大多數正是你在ViewPager基於Fragment使用嵌套Fragments併爲ViewPager您創建適配器這樣的:

MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(this.getFragmentManager()); 

相反,你應該使用getChildFragmentManager()綁定嵌套的片段:

MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(this.getChildFragmentManager()); 

而且,您不應該通過構造函數將數據傳遞到Fragment,因爲數據在配置更改後無法存活,並且會出現不好的情況。改爲使用Bundle

+1

嘿。真的非常感謝你的幫助。但是,我不明白爲什麼使用this.getChildFragmentManager將解決問題。從http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html,它通過getSupportFragmentManager()(FragmentActivity是ViewPager的所有者)使用FragmentActivity的片段管理器。它不使用ArrayListFragment的片段管理器(ArrayListFragment(s)是ViewPager的可滑動內容) – 2013-03-23 16:26:00

+0

在this.getChildFragmentManager()中,它返回片段管理器的紫色和藍色片段。這與正在使用ViewPager所有者的片段管理器的官方示例不同。因此,這讓我感到困惑。 – 2013-03-23 16:28:46

+1

我不確定這是否真的回答了我自己的問題。我認爲給出的例子是活動中的片段。使用getFragmentManager是有道理的。但是,如果對於片段內的嵌套片段,則需要使用getChildFragmentManager。這是Google發佈的一個「規則」:http://developer.android.com/about/versions/android-4.2.html#NestedFragments – 2013-03-23 16:48:55

12

全球工作測試解決方案。

getSupportFragmentManager()保留空引用一些時間和查看尋呼機不創建新的片段實例。因爲它找到對同一片段的引用。所以過來這個用簡單的方法解決問題。

不要

new PagerAdapter(getSupportFragmentManager(), fragments);

new PagerAdapter(getChildFragmentManager() , fragments);

+0

很好的解釋。謝謝 – 2015-09-01 19:43:39

0

在我來說,我是正確調用

MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(this.getChildFragmentManager()); 

但隨後在嵌套的片段,我嘗試使用,以取代另一個容器片段:

getFragmentManager() 

你需要去的活動,並呼籲

getActivity().getSupportFragmentManager(); 
0

在我的情況下工作後,將其添加到我的FragmentPagerAdapter

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

,我也用getChildFragmentManager()像Luksprog說的

0

簡單使用FragmentStatePagerAdapter代替FragmentPagerAdapter

可以使用new MyFragmentPagerAdapter(this.getChildFragmentManager())

希望它會幫助你:)