Очистить задний стек, используя фрагменты - PullRequest
223 голосов
/ 31 мая 2011

Я портировал свое Android-приложение на сотовые и сделал большой рефакторинг, чтобы использовать фрагменты. В моей предыдущей версии, когда я нажимал кнопку «Домой», я делал ACTIVITY_CLEAR_TOP для сброса заднего стека.

Теперь мое приложение - это просто одно действие с несколькими фрагментами, поэтому, когда я нажимаю кнопку «Домой», я просто заменяю один из фрагментов внутри него. Как очистить свой стек без необходимости использовать startActivity с флагом ACTIVITY_CLEAR_TOP?

Ответы [ 14 ]

394 голосов
/ 01 июня 2011

Я опубликовал нечто подобное здесь

Из ответа Иоахима от Дайан Хакборн:

http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42

Я закончил тем, что использовал:

FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {    
    fm.popBackStack();
}

Но в равной степени можно было бы использовать что-то вроде:

((AppCompatActivity)getContext()).getSupportFragmentManager().popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)

, который выведет все состояния до названного.Затем вы можете просто заменить фрагмент на то, что вы хотите

145 голосов
/ 18 октября 2014

Чтобы ответить на комментарий @ Warpzit и упростить поиск для других.

Использование:

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
37 голосов
/ 04 марта 2015

При всем уважении ко всем вовлеченным сторонам; Я очень удивлен, увидев, как многие из вас могут очистить весь стек обратно с помощью простого

fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Согласно документации Android (в отношении аргумента name - "ноль" в заявленных рабочих предложениях).

Если ноль, выталкивается только верхнее состояние

Теперь я понимаю, что мне не хватает знаний о ваших конкретных реализациях (например, сколько записей у вас в заднем стеке на данный момент времени), но я бы поставил все свои деньги на принятый ответ, ожидая четко определенное поведение в отношении более широкого спектра устройств и поставщиков:

(для справки, кое-что вместе с этим)

FragmentManager fm = getFragmentManager(); // or 'getSupportFragmentManager();'
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {    
    fm.popBackStack();
}
17 голосов
/ 14 октября 2014

Принятого ответа мне было недостаточно. Я должен был использовать:

FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
    fm.popBackStackImmediate();
}
16 голосов
/ 30 июля 2015

Работает для меня и простой способ без использования цикла:

 FragmentManager fragmentManager = getSupportFragmentManager();
 //this will clear the back stack and displays no animation on the screen
 fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
15 голосов
/ 14 мая 2015

Очистить backstack без циклов

String name = getSupportFragmentManager().getBackStackEntryAt(0).getName();
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Где name - это параметр addToBackStack ()

getSupportFragmentManager().beginTransaction().
                .replace(R.id.container, fragments.get(titleCode))
                .addToBackStack(name)
8 голосов
/ 31 августа 2015

Я просто хотел добавить: -

Выход из backstack с использованием следующего

fragmentManager.popBackStack ()

- это просто удаление фрагментов из транзакции, ни в коем случае не удаление фрагмента с экрана. Поэтому в идеале он может быть невидим для вас, но может быть два или три фрагмента, накладываемые друг на друга, и при нажатии клавиши «назад» пользовательский интерфейс может выглядеть загроможденным, сложенным.

Просто приведу простой пример: -

Предположим, у вас есть фрагмент A, который загружает Fragmnet B с использованием fragmanager.replace () , а затем мы добавляем addToBackStack, чтобы сохранить эту транзакцию. Итак, поток: -

ШАГ 1 -> FragmentA-> FragmentB (мы переместились во FragmentB, но Fragment A находится в фоновом режиме, не виден).

Теперь вы выполняете некоторую работу во фрагменте B и нажимаете кнопку «Сохранить», которая после сохранения должна вернуться к фрагменту A.

ШАГ 2-> При сохранении фрагмента B мы возвращаемся к фрагменту A.

ШАГ 3 -> Такая распространенная ошибка будет ... во фрагменте B мы сделаем фрагмент Manager.replace () фрагментB с фрагментом A.

Но что на самом деле происходит, мы снова загружаем Фрагмент A, заменяя FragmentB. Итак, теперь есть два фрагмента A (один из STEP-1 и один из этого STEP-3).

Два экземпляра фрагментов A накладываются друг на друга, которые могут быть невидимы, но они есть.

Таким образом, даже если мы очищаем backstack вышеупомянутыми методами, транзакция очищается, но не фактические фрагменты. Так что в идеальном случае в таком конкретном случае при нажатии кнопки сохранения вам просто нужно вернуться к фрагменту A, просто выполнив fm.popBackStack () или fm.popBackImmediate () .

Так что правильно Step3-> fm.popBackStack () вернуться к фрагменту A, который уже находится в памяти.

3 голосов
/ 19 августа 2016

Просто используйте этот метод и передайте тег Context & Fragment, в который нам нужно удалить фрагменты обратного удара.

Usage

clearFragmentByTag(context, FragmentName.class.getName());



public static void clearFragmentByTag(Context context, String tag) {
    try {
        FragmentManager fm = ((AppCompatActivity) context).getSupportFragmentManager();

        for (int i = fm.getBackStackEntryCount() - 1; i >= 0; i--) {
            String backEntry = fm.getBackStackEntryAt(i).getName();
            if (backEntry.equals(tag)) {
                break;
            } else {
                 fm.popBackStack();
            }
        }
    } catch (Exception e) {
        System.out.print("!====Popbackstack error : " + e);
        e.printStackTrace();
    }
}
3 голосов
/ 23 июля 2016

Читая документацию и изучая, что такое идентификатор фрагмента, кажется, что это просто индекс стека, так что это работает:

fragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Ноль (0) - это нижняя часть стека, поэтому всплытие до него включительно очищает стек.

CAVEAT: Хотя вышеперечисленное работает в моей программе, я немного сомневаюсь, потому что документация FragmentManager фактически никогда не утверждает, что id является индексом стека. Это имеет смысл, и все мои журналы отладки показывают, что это так, но, возможно, в некоторых особых обстоятельствах это не так? Кто-нибудь может подтвердить это так или иначе? Если это так, то вышеупомянутое является лучшим решением. Если нет, то это альтернатива:

while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }
1 голос
/ 18 января 2019

Это работает для меня, попробуйте это:

public void clearFragmentBackStack() {
        FragmentManager fm = getSupportFragmentManager();
        for (int i = 0; i < fm.getBackStackEntryCount() - 1; i++) {
            fm.popBackStack();
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...