在我的場景里,會創建多個Fragment,Fragment之間可以互相跳轉,點擊回傳鍵需要一級一級往上回傳,因此需要一個類似于Activity的回退堆疊,當然沒必要做到Activity那么復雜,滿足先進先出的效果即可,
添加Fragment回退堆疊
添加個Fragment,并將其加入回退堆疊,代碼如下:
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.frag_container, fragment)
.addToBackStack(null)
.commitAllowingStateLoss();
方法addToBackStack表示將Fragment加入到回退堆疊中,
在回傳時,Fragment出堆疊的邏輯如下:
FragmentManager fragmentManager = getSupportFragmentManager();
int backStackCount = fragmentManager.getBackStackEntryCount();
if (backStackCount > 0) {
fragmentManager.popBackStack();
}
方法popBackStack將一個Fragment出堆疊,呼叫前可以先通過getBackStackEntryCount方法判斷當前回退堆疊是否還有Fragment,
獲取頂部的Fragment
我的場景中,經常要獲取堆疊頂的Fragment進行操作,然而沒有找到直接獲取堆疊頂Fragment的方法,在最初的實作中,借用了Stack來實作我的邏輯,
private final Stack<Fragment> mFragmentStack = new Stack<>();
public void addFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.frag_container, fragment)
.addToBackStack(null)
.commitAllowingStateLoss();
mFragmentStack.push(fragment);
}
public void popFragment() {
FragmentManager fragmentManager = getSupportFragmentManager();
int backStackCount = fragmentManager.getBackStackEntryCount();
if (backStackCount > 0) {
fragmentManager.popBackStack();
mFragmentStack.pop();
}
}
public Fragment getTopFragment() {
return mFragmentStack.peek();
}
然而使用Stack后發現線上版本會發生crash,mFragmentStack里的Fragment和FragmentManager中的Fragment可能不一致,主要原因是Activity狀態恢復導致的,Stack資料沒有saveInstanceState,Activity恢復時執行mFragmentStack.peek會導致EmptyStackException,
要修復這個問題,可以將Stack資料也進行狀態保存,但我仔細想過后覺得,Stack和FragmentManager的作用是一致的,加一個Stack本身是不合理的,后續代碼變更,也很難保證Stack和FragmentManager回退堆疊資料是一致的,為此我開始想另外的解決方案,
回到我最開始的需求,我就是想獲取頂部的Fragment,能不能用FragmentManager提供的介面來實作呢?閱讀相關原始碼后,有個方法引起了我的注意:
/**
* Return the BackStackEntry at index <var>index</var> in the back stack;
* entries start index 0 being the bottom of the stack.
*/
@NonNull
public BackStackEntry getBackStackEntryAt(int index) {
return mBackStack.get(index);
}
獲取到的BackStackEntry有id和name屬性,為此我想到一個辦法:
public Fragment getTopFragment() {
int count = getSupportFragmentManager().getBackStackEntryCount();
FragmentManager.BackStackEntry entry = getSupportFragmentManager().getBackStackEntryAt(count - 1);
return getSupportFragmentManager().findFragmentByTag(entry.getName());
}
該代碼中,首先獲取回退堆疊數量,然后通過getBackStackEntryAt方法,獲取最后一個回退堆疊資料,最后通過findFragmentByTag找到頂部的Fragment,不過這里要注意的是,在添加回退堆疊時,需要設定tag,具體代碼如下:
public void addFragment(Fragment fragment) {
String tag = getFragmentTag();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.frag_container, fragment, tag)
.addToBackStack(tag)
.commitAllowingStateLoss();
}
上面代碼中,add和addToBackStack方法都指定了同一個tag,保證后續能夠通過findFragmentByTag找到相應的Fragment,
方案最終驗證OK,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/544074.html
標籤:Android
上一篇:Opengl ES之踩坑記
