Является ли это правильным способом очистки заднего стека фрагментов при выходе из глубоко вложенного стека? - PullRequest
126 голосов
/ 27 апреля 2011

Я использую библиотеку Android Compatibility для реализации фрагментов и расширил образец макета, чтобы фрагмент содержал кнопку, которая запускает другой фрагмент.

В панели выбора слева у меня есть 5 элементов для выбора - A B C D E.

Каждый загружает фрагмент (через FragmentTransaction:replace) в области сведений - a b c d e

Теперь я расширил фрагмент e, добавив в него кнопку, которая загружает другой фрагмент e1 также в области сведений. Я сделал это для метода onClick фрагмента e следующим образом:

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 ]

247 голосов
/ 13 мая 2011

Ну, есть несколько способов сделать это в зависимости от предполагаемого поведения, но эта ссылка должна дать вам все лучшие решения, и неудивительно, что это от Дайан Хакборн

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),
60 голосов
/ 24 июля 2013

Другое чистое решение, если вы не хотите извлекать все записи стека ...

getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().beginTransaction().replace(R.id.home_activity_container, fragmentInstance).addToBackStack(null).commit();

Это сначала очистит стек, а затем загрузит новый фрагмент, так что в любой моментв стеке будет только один фрагмент

25 голосов
/ 09 ноября 2012

Благодаря ответу 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 */
7 голосов
/ 19 июня 2015

Я много исследовал очистку Backstack и, наконец, вижу Транзакция 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 может быть использован для контроля, выталкивается ли само названное состояние.Если ноль, выталкивается только верхнее состояние.
3 голосов
/ 29 февраля 2016

Я использую код, аналогичный тем, которые используют цикл while, но я вызываю счетчик записей в каждом цикле ... поэтому я предполагаю, что он несколько медленнее

FragmentManager manager = getFragmentManager();
while (manager.getBackStackEntryCount() > 0){
        manager.popBackStackImmediate();
    }
0 голосов
/ 06 марта 2013
    // pop back stack all the way
    final FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
    int entryCount = fm.getBackStackEntryCount(); 
    while (entryCount-- > 0) {
        fm.popBackStack();
    }
...