Является ли это правильным способом очистки заднего стека фрагмента при выходе из глубоко вложенного стека?
Я использую библиотеку Android Compatibility для реализации фрагментов и расширил образец макета, чтобы фрагмент содержал кнопку, которая запускает другой фрагмент.
В панели выбора слева у меня есть 5 выбираемых пунктов - A B C D E
,
Каждый загружает фрагмент (через FragmentTransaction:replace
) в панели подробностей - a b c d e
Теперь я расширил фрагмент e
содержать кнопку, которая загружает другой фрагмент e1
также в области сведений. Я сделал это на фрагменте e
метод onClick следующим образом:
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(R.id.details_frag, newFrag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
Если я сделаю следующие выборы:
E - e - e1 - D - E
Затем фрагмент e
находится в области сведений. Это нормально и то, что я хочу. Тем не менее, если я ударил back
Кнопка в этот момент ничего не делает. Я должен нажать на нее дважды, потому что e1
все еще в стеке. Кроме того, после щелчка я получил исключение нулевого указателя в onCreateView:
Чтобы "решить" эту проблему, я добавлял следующее A B C D E
выбрано:
FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
fm.popBackStack();
}
Просто интересно, правильное ли это решение или я должен делать что-то другое?
6 ответов
Ну, есть несколько способов сделать это в зависимости от предполагаемого поведения, но эта ссылка должна дать вам все лучшие решения, и неудивительно, что это от Dianne Hackborn
http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42
По сути у вас есть следующие варианты
- Используйте имя для вашего начального состояния стека и используйте
FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)
, - использование
FragmentManager.getBackStackEntryCount()
/getBackStackEntryAt().getId()
получить идентификатор первой записи в заднем стеке иFragmentManager.popBackStack(int id, FragmentManager.POP_BACK_STACK_INCLUSIVE)
, FragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
должен выкинуть весь задний стек... Я думаю, что документация для этого просто неверна. (На самом деле, я думаю, что это не распространяется на случай, когда вы проходите вPOP_BACK_STACK_INCLUSIVE
),
Другое чистое решение, если вы не хотите извлекать все записи стека...
getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().beginTransaction().replace(R.id.home_activity_container, fragmentInstance).addToBackStack(null).commit();
Это сначала очистит стек, а затем загрузит новый фрагмент, поэтому в любой данный момент у вас будет только один фрагмент в стеке
Спасибо Joachim ответ, я использую код, чтобы очистить все записи обратно стека, наконец.
// In your FragmentActivity use getSupprotFragmentManager() to get the FragmentManager.
// Clear all back stack.
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
for (int i = 0; i < backStackCount; i++) {
// Get the back stack fragment id.
int backStackId = getSupportFragmentManager().getBackStackEntryAt(i).getId();
fm.popBackStack(backStackId, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} /* end of for */
Я много исследовал очистку Backstack и наконец увидел Transaction BackStack и его управление. Вот решение, которое работает лучше всего для меня.
// CLEAR BACK STACK.
private void clearBackStack() {
final FragmentManager fragmentManager = getSupportFragmentManager();
while (fragmentManager.getBackStackEntryCount() != 0) {
fragmentManager.popBackStackImmediate();
}
}
Вышеприведенный метод перебирает все транзакции в backstack и сразу удаляет их по одной.
Примечание: приведенный выше код иногда не работает, и я сталкиваюсь с ANR из-за этого кода, поэтому, пожалуйста, не пытайтесь это сделать.
Обновленный ниже метод удаляет весь фрагмент этого "имени" из backstack.
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE);
- name Если не ноль, это имя предыдущего обратного состояния для поиска; если найдено, все состояния до этого состояния будут вытолкнуты.
- Флаг POP_BACK_STACK_INCLUSIVE может быть использован для управления тем, не вышло ли само именованное состояние. Если ноль, только верхнее состояние выталкивается.
Я использую код, подобный тем, которые используют цикл while, но я вызываю счетчик записей в каждом цикле... так что я предполагаю, что он несколько медленнее
FragmentManager manager = getFragmentManager();
while (manager.getBackStackEntryCount() > 0){
manager.popBackStackImmediate();
}
Как написано в разделе Как извлечь фрагмент из бэкстэка и здесь Ларшем, мы можем вставить несколько фрагментов сверху вниз в конкретный тег (вместе с тегированным фрагментом), используя этот метод:
fragmentManager?.popBackStack ("frag", FragmentManager.POP_BACK_STACK_INCLUSIVE);
Замените "фрагмент" тегом вашего фрагмента. Помните, что сначала мы должны добавить фрагмент в стопку с помощью:
fragmentTransaction.addToBackStack("frag")
Если мы добавим фрагменты с addToBackStack(null)
, таким образом мы не будем выделять фрагменты.
// pop back stack all the way
final FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
int entryCount = fm.getBackStackEntryCount();
while (entryCount-- > 0) {
fm.popBackStack();
}