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

Я использую библиотеку 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();
    }
Другие вопросы по тегам