2014-02-09 46 views
18

我在導航抽屜中列出了許多頁面/片段,用戶可能會經常在這些頁面/片段之間進行切換,我希望他們能夠在後臺導航,但是我只需要一個實例的背景中的每個片段,以便用戶不必爲了退出應用程序而壓倒瘋狂的次數。我無法弄清楚如何在沒有頁面被移除的情況下有效'重新排序'後臺'。Android Reorder Fragment Backstack

目前,當我改變頁面我是用這個代碼來改變片段,並確保它只是在後面堆一次

if (mFragMgr == null) { 
     mFragMgr = getSupportFragmentManager(); 
    } 

    String backStateName = fragmentDescriptor.name(); 
    boolean fragmentPopped = mFragMgr.popBackStackImmediate(backStateName, 0); 
    if (!fragmentPopped){ 
     mFragMgr.beginTransaction() 
     .remove((Fragment) mFragment) 
     .replace(R.id.content_frame, (Fragment) mFragment) 
     .addToBackStack(backStateName) 
     .commit(); 
    } 

我onBackPressed

使用此代碼
@Override 
    public void onBackPressed() { 
     if (mFragMgr.getBackStackEntryCount() > 0) { 
      mFragMgr.popBackStackImmediate(); 
     } else { 
      super.onBackPressed(); 
     } 
    } 

該作品但這意味着它會刪除我不想刪除的網頁。例如:

當我的用戶訪問6頁順序A > B > C > D > E > C因爲我做了刪除我期待下面的堆棧:

      [E] [C] 
        [D] [D] [E] 
       [C] [C] [C] [D] 
     [B] [B] [B] [B] [B] 
[A] -> [A] -> [A] -> [A] -> [A] -> [A] 

但我實際上得到的是下面的 - 它彈出的一切達與名稱匹配的元素,這與我是否包含「.remove((Fragment)mFragment)」無關 - (我現在已經意識到remove不會影響後臺,所以不需要指向那出):

      [E] 
        [D] [D] 
       [C] [C] [C] [C] 
     [B] [B] [B] [B] [B] 
[A] -> [A] -> [A] -> [A] -> [A] -> [A] 

如果添加到堆棧中,我得到了以下的時候,不使用名稱,而是使用空:

        [C] 
          [E] [E] 
        [D] [D] [D]  
       [C] [C] [C] [C] 
     [B] [B] [B] [B] [B] 
[A] -> [A] -> [A] -> [A] -> [A] -> [A] 

我怎樣才能得到我所期望的行爲?有沒有可能,或者我需要自己記錄這些變化,並完全跳過後臺?

+0

我試圖找到有效的方法來做到這一點,我把一些精力投入到我的問題 - 這將是很好,如果該人downvoting會有勇氣去說爲什麼 –

+0

對不起,在'FragmentManager沒有方法'用於從後端堆棧中移除'Fragment'狀態的API。該API僅公開了推送和彈出的標準堆棧機制。 – corsair992

+0

我認爲可能是這種情況。但我的用例看起來像是一個非常有效的,相當普遍的需求,並且您可以通過活動實現類似。我希望有人可能知道一個輔助類或其他東西來實現這個 –

回答

20

沒有API來做到這一點,但我becuse上週知道同樣的事情,
我把它作爲一個練習的實現了它自己。

我的方法可以讓你刪除從堆棧中的任何位置Fragment,這是通過使用refrection修改存儲在FragmentManagerImplBackStackRecord返回堆棧信息的內部變量來實現的。

有幾個重要的變量:

  • mBackStack - 存儲BackStackRecord s表示保持Fragment信息,以前的那些,動畫等
  • mActive - 所有添加的Fragment小號
  • mAvailBackStackIndices - 商店新插入的記錄可以使用的索引,即null值的索引mActive
  • 和其他

測試與150+ Fragment S和不能發現任何泄漏,但只監測堆在DDMS,並沒有執行任何其他內存分析。
因此,因爲someting可能會被破壞,請瀏覽代碼,重新測試它,查看是否有人提供了更好的答案,並重新考慮是否真的需要在您的項目中執行此操作。

我上傳的代碼爲gist on GitHub,希望有幫助。

+0

一個有趣的方法,謝謝。它需要很多代碼才能正常工作,我會在本週晚些時候深入研究它,當我有更多時間時 –

+1

正如我之前所說的,我喜歡的代碼太多了,ho wever,我相信這對於一些遊客來說是一個正確的解決方案,並且你需要付出一些努力才能把它放在一起,這樣我才能獎勵你! –

0

如果您想在其之前重新使用片段,只需首先隱藏所有片段並一次顯示所需的片段。通過這樣做,您可以重複使用您的片段而不必刪除它們,也無需重新加載片段。但是確保在實現它之前,您必須將片段添加到backstack。

+0

,如果你有2000個碎片,你最終會出現OOM。 –