2014-09-19 48 views
9

UPDATE從FragmentStatePagerAdapter

刪除片段後,這個問題的一些主要的戰鬥,並從我設法解決這個問題,使用戶有所幫助。 這就是我的clearProgressUpTo現在的樣子。

public void clearProgressUpTo(int progress) { 
    boolean deleted = false; 

    for (int i = fragments.size() - 1; i > 0; i--) { 
     int key = fragments.keyAt(i); 
     if (key != progress) { 
      fragments.delete(key); 
      deleted = true; 
     } else { 
      break; 
     } 
    } 

    if (deleted) 
     notifyDataSetChanged(); //prevents recursive call (and IllegalStateException: Recursive entry to executePendingTransactions) 

    while (mSavedState.size() > progress) { 
     mSavedState.remove(mSavedState.size()-1); 
    } 

} 

爲什麼我notifyDataSetChanged後這樣做的原因是因爲initiateItem再次充盈我的mSavedState。我確信在通知我的adapter後不會包含這些Fragments中的任何一個。

此外,如果你想這樣做,將mSaveState改爲protected,這樣你就可以從擴展類(在我的例子VerticalAdapter)中得到它。

我忘了提,我使用FragmentStatePagerAdapter fix by Adam Speakman解決我的問題。

////////////////////////////////////////////// /////// 問題部分 /////////////////////////////////////// ///////////////

我遇到的問題是我需要完全刪除Fragments中的FragmentStatePagerAdapter

我已經做就可以了POSITION_NONE修復,但舊的片段似乎依然保持完好。

建設

因爲我ViewPager的建設是不尋常的我被迫把裏面我VerticalAdater延伸FragmentStatePagerAdapter一個SparseArray保存我的所有片段。

public class VerticalAdapter extends FragmentStatePagerAdapter { 

private SparseArray<Fragment> fragments = new SparseArray<Fragment>(); 
... 

@Override 
public Fragment getItem(int position) { 
    return getFragmentForPosition(position); 
} 

@Override 
public int getCount() { 
    return fragments.size(); 
} 

問題

我已經負責清理所有Fragments了一些點在我FragmentStatePagerAdapter的特殊方法。它的運作良好,但我不能擺脫的問題是清除FragmentStatePagerAdapter內的ArrayList。甚至儘管我清除SparseArrayFragmentStatePagerAdapterVerticalAdapter擴展仍持我不希望有那裏的FragmentsArrayList。正因爲如此,當我創建新的Fragments他們有舊的狀態。

public void clearProgressUpTo(int progress) { 
    boolean deleted = false; 

    for (int i = fragments.size() - 1; i > 0; i--) { 
     int key = fragments.keyAt(i); 
     if (key != progress) { 
      fragments.delete(key); 
      deleted = true; 
     } else { 
      break; 
     } 
    } 

    if (deleted) 
     notifyDataSetChanged(); //prevents recursive call (and IllegalStateException: Recursive entry to executePendingTransactions) 
} 

如果您需要更多信息/代碼,請告訴我的意見,我會盡量提供儘可能多的信息,我可以。

我不知道如何解決這個問題,讓任何輸入,將不勝感激。

編輯

添加請求的代碼。

private Fragment getFragmentForPosition(int position) { 
    return fragments.get(getKeyForPosition(position)); 
} 

public int getKeyForPosition(int position) { 
    int key = 0; 
    for (int i = 0; i < fragments.size(); i++) { 
     key = fragments.keyAt(i); 
     if (i == position) { 
      return key; 
     } 
    } 
    return key; 
} 
+0

post'getFragmentForPosition(position);'please。 – mmlooloo 2014-09-19 08:58:50

+0

添加了您請求的代碼。 – JakubW 2014-09-19 09:03:31

+0

從我的'Adatper'這裏缺少的唯一東西是方法'setProgress',它填充'fragments'數組。 爲什麼我知道它的舊狀態?因爲'setProgress'正在用''Fragments'的'newinstance'重新加載整個'fragments'數組。 另外''ViewPager'數組內'Fragments'的ID與'setProgress'之前的相同。 – JakubW 2014-09-22 06:10:10

回答

7

FragmentStatePageAdapter在破壞片段的同時保存片段的狀態,以便後者在片段重新創建時保存的狀態將應用於該片段。

片段狀態存儲在私有成員變量中。因此我們不能擴展當前的實現來添加刪除已保存狀態的功能。

我已經克隆了當前的FragmentStatePagerAdapter實現,幷包含保存的狀態刪除功能。這裏是gist reference

/** 
    * Clear the saved state for the given fragment position. 
    */ 
    public void removeSavedState(int position) { 
     if(position < mSavedState.size()) { 
      mSavedState.set(position, null); 
     } 
    } 

在你clearProgressUpTo方法,每當你從稀疏數組中刪除片段,調用這個方法,它清除掉保存的狀態該片斷。

+0

我昨天解決了我的問題,並將其與您的答案連接起來。 我確實從FragmentStatePagerAdapter中獲取了mSaveState,並在我正在擺脫的元素上使用了mSaveState.remove。 接受你的答案,因爲它最接近解決這個問題。 – JakubW 2014-09-24 06:43:31

+0

嗨JakubW ...你能分享你的答案 – amity 2017-05-08 08:20:39

7

您的問題不是由您使用SparseArray引起的。事實上,你遇到了FragmentStatePagerAdapter的一個bug。我花了一些時間閱讀FragmentStatePagerAdapter,ViewPager和FragmentManagerImpl的源代碼,然後發現你的新片段具有舊片段的原因:

FragmentStatePagerAdapter在刪除它們時保存舊片段的狀態,如果稍後將新片段添加到適配器,保存的狀態將傳遞到您在同一位置的新片段。

我GOOGLE了這個問題,並找到解決方案,下面是它的鏈接: http://speakman.net.nz/blog/2014/02/20/a-bug-in-and-a-fix-for-the-way-fragmentstatepageradapter-handles-fragment-restoration/

的源代碼可以在這裏找到: https://github.com/adamsp/FragmentStatePagerIssueExample/blob/master/app/src/main/java/com/example/fragmentstatepagerissueexample/app/FixedFragmentStatePagerAdapter.java

這個解決方案的核心思想是重寫FragmentStatePagerAdapter和使用字符串標記來標識適配器中的每個片段。由於每個片段都有不同的標記,因此很容易識別新的片段,然後不會將保存的狀態傳遞給新的片段。

最後,感謝Adam Speakman是該解決方案的作者。

+0

我在發佈SO之前就已經使用了這個錯誤修復,但它沒有解決問題:C 我打算再次嘗試一下併發布我的結果。 – JakubW 2014-09-22 12:21:03

+0

也許我誤解了你的問題,我會在你解決問題後檢查你的帖子並說清楚。 – 2014-09-22 14:05:09

+0

我正在嘗試使用它,但現在問題仍然存在。但它似乎爲我解決了其他問題。 但是這個解決方案還有另一個問題。當我將我的'片段'從'{1,2,3,7}'擴展到'{1,2,3,4,7}'時,TAG不會被插入到新的'片段'(4)中。奇怪的是,它在屏幕旋轉後工作。 – JakubW 2014-09-23 08:20:31

相關問題