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

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

В области выбора слева у меня есть 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();
}

Просто интересно, правильно ли это решение или я должен делать что-то другое?

Ответ 1

Ну, есть несколько способов сделать это в зависимости от предполагаемого поведения, но эта ссылка должна дать вам все лучшие решения и не удивительно, что это 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),

Ответ 2

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

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

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

Ответ 3

Благодаря ответу 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 */

Ответ 4

Я много исследовал для очистки 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 Если не null, это имя предыдущего обратного состояния искать; если найдено, все состояния до этого состояния будут выскочены.
  • Флаг POP_BACK_STACK_INCLUSIVE может использоваться для управления выводом самого имени. Если значение null, то выводится только верхнее состояние.

Ответ 5

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

FragmentManager manager = getFragmentManager();
while (manager.getBackStackEntryCount() > 0){
        manager.popBackStackImmediate();
    }

Ответ 6

    // pop back stack all the way
    final FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
    int entryCount = fm.getBackStackEntryCount(); 
    while (entryCount-- > 0) {
        fm.popBackStack();
    }