[英]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();
}
}
這有效,但這意味着它刪除了我不想刪除的頁面。 例:
當我的用戶按照A > B > C > D > E > C
的順序訪問6頁時,因為我正在進行刪除,我期望以下堆棧:
[E] [C]
[D] [D] [E]
[C] [C] [C] [D]
[B] [B] [B] [B] [B]
[A] -> [A] -> [A] -> [A] -> [A] -> [A]
但實際得到的是以下內容 - 它會將所有內容彈出到與名稱相匹配的元素,這與我是否包含“.remove((Fragment)mFragment)”無關 - ( 我已經意識到了remove不會影響backstack,所以不需要指出那個 ):
[E]
[D] [D]
[C] [C] [C] [C]
[B] [B] [B] [B] [B]
[A] -> [A] -> [A] -> [A] -> [A] -> [A]
如果我不使用名稱,而是在添加到backstack時使用null,我會得到以下內容:
[C]
[E] [E]
[D] [D] [D]
[C] [C] [C] [C]
[B] [B] [B] [B] [B]
[A] -> [A] -> [A] -> [A] -> [A] -> [A]
我怎樣才能得到我期望的行為? 是否有可能或我是否需要自己記錄更改並完全跳過后台堆疊?
沒有API可以做到這一點,但是因為我上周想知道同樣的事情,
我把它作為一個練習,自己實現它。
我的方法允許您從Backstack中的任何位置刪除Fragment
,這可以通過使用refrection來修改存儲FragmentManagerImpl和BackStackRecord中的Backstack信息的內部變量來實現。
幾個重要變量:
mBackStack
- 存儲包含Fragment
信息的BackStackRecord
,以前的,動畫等 mActive
- 所有添加Fragment
mAvailBackStackIndices
- 存儲新插入記錄可以使用的索引,即mActive
的null
值mActive
使用150+ Fragment
測試並且無法注意到任何泄漏,但僅監視DDMS
的堆並且未執行任何其他內存分析。
因此,可能會破壞某些方法,探索代碼,重新測試它,看看是否有人提供了更好的答案,並重新考慮是否真的需要在項目中執行此操作。
如果要在它之前重用片段,只需先隱藏所有片段並一次顯示所需的片段。 通過這樣做,您可以重用您的片段而無需刪除它們,也無需重新加載片段。 但是在實現之前一定要確保將片段添加到backstack中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.