it-swarm.com.ru

Очистить задний стек, используя фрагменты

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

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

215
biquillo

Я разместил нечто подобное здесь

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

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();
}

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

FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)

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

373
PJL

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

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

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
132
Morten Holmgaard

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

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();
}
36
dbm

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

FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
    fm.popBackStackImmediate();
}
17
belphegor

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

 FragmentManager fragmentManager = getSupportFragmentManager();
 //this will clear the back stack and displays no animation on the screen
 fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
16
Md Mohsin

Очистить бэкстек без петель

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

Где имя это параметр addToBackStack ()

getSupportFragmentManager().beginTransaction().
                .replace(R.id.container, fragments.get(titleCode))
                .addToBackStack(name)
13
georgehardcore

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

Выскочить из backstack, используя следующие

fragmentManager.popBackStack ()

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

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

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

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

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

ШАГ 2-> При сохранении FragmentB мы возвращаемся к FragmentA.

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

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

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

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

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

8
Nicks

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

fragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);

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

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

while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }
3
trans

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

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

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();
    }
}
2
Arhat Baid

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

public void clearFragmentBackStack() {
        FragmentManager fm = getSupportFragmentManager();
        for (int i = 0; i < fm.getBackStackEntryCount() - 1; i++) {
            fm.popBackStack();
        }
    }
2
Alok Singh

Я получил это работает так:

public void showHome() {
    getHandler().post(new Runnable() {
        @Override
        public void run() {
            final FragmentManager fm = getSupportFragmentManager();
            while (fm.getBackStackEntryCount() > 0) {
                fm.popBackStackImmediate();
            }
        }
    });
}
1
saulobrito
private boolean removeFragFromBackStack() {
    try {
        FragmentManager manager = getSupportFragmentManager();
        List<Fragment> fragsList = manager.getFragments();
        if (fragsList.size() == 0) {
            return true;
        }
        manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}
0
user3509903
    private void clearBackStack(){
        SupportFragmentManaer fm = getSupportFragmentManager();
        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

Вызов этого метода будет очень аккуратным.

  1. Петля не требуется.
  2. Если вы используете анимацию во фрагментах, она не будет отображать слишком много анимаций. Но с помощью цикла будет.
0
Wajid Ali

Привет ~ Я нашел решение, которое гораздо лучше, из: https://Gist.github.com/ikew0ng/8297033

    /**
 * Remove all entries from the backStack of this fragmentManager.
 *
 * @param fragmentManager the fragmentManager to clear.
 */
private void clearBackStack(FragmentManager fragmentManager) {
    if (fragmentManager.getBackStackEntryCount() > 0) {
        FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(0);
        fragmentManager.popBackStack(entry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }
}
0
Chenxi