Избегайте добавления одного и того же фрагмента несколько раз в backStack.

У меня есть активность с 4 фрагментами. Я хотел бы избежать ситуаций, когда пользователь нажимает 100 раз перед выходом. Когда фрагмент установлен, он добавляется в задний стек. Например: Пользователь устанавливает фрагменты в таком порядке: 1, 2, 3, 4, затем он устанавливает frag 2, а затем 4. Мой backStack выглядит так (виден фрагмент 4): 2, 4, 3, 2, 1 и выход. Я бы хотел, чтобы мой backStack выглядел так: 2, 3, 1 и выход.

Я пытался решить свою проблему с помощью popBackStackImmediate(string, int flags), как в этом посте: Предотвратить многократное стекирование одного и того же фрагмента ( addToBackStack ) Но мой backStack выглядит как (с видимыми 4) 2, 1 и выход. Я пришел к выводу, что popBackStackImmediate() удаляет стеки поверх извлеченного стека (надеюсь, вы понимаете, о чем я).

private void setFragment(Fragment fragment) {

        String backStateName = fragment.getClass().getName();

        FragmentManager manager = getSupportFragmentManager();
        boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);

        if (!fragmentPopped){ //fragment not in back stack, create it.
            FragmentTransaction ft = manager.beginTransaction();
            ft.replace(R.id.main_frame, fragment);
            ft.addToBackStack(backStateName);
            mMainNav.setItemBackgroundResource(R.color.PopWindowBorder_HomeRenovationfragment);
            ft.commit();
        }
    }

Я ожидаю, что каждый фрагмент будет находиться в заднем стеке не более одного раза, не нарушая порядок заднего стека, чтобы иметь задний стек, который выглядит так: 2, 3, 1 и выход. :)


person mathislr    schedule 22.07.2019    source источник
comment
Рассматривали ли вы возможность блокировки пользователя от фактического добавления фрагмента более одного раза? Это звучит более естественно для меня.   -  person ror    schedule 22.07.2019
comment
Вы рассматривали возможность использования viewpager с адаптером фрагмента?   -  person a_local_nobody    schedule 22.07.2019
comment
@a_local_nobody мне тоже нравится. Но это невозможно, если вы заблокируете его, чтобы добавить второй раз, это не сработает. На самом деле мне нужно удалить старый стек, и popBackStack прекрасно работает, но подавляет другие стеки... Когда я его блокирую, я получаю этот задний стек (с видимым фрагом 4): 4, 3, 2, 1 и выход. Я думаю, что это вызовет исключение, но в любом случае я не ожидаю такого результата :)   -  person mathislr    schedule 22.07.2019
comment
@a_local_nobody, что такое viewPager с адаптером фрагментов (извините, я новичок ^^). У вас есть ссылка, которая могла бы просветить меня?   -  person mathislr    schedule 22.07.2019
comment
нет проблем, просмотрщик с адаптером фрагмента обычно используется, когда вы хотите перемещаться между различными фрагментами, взгляните на это: developer.android.com/training/animation/screen-slide. Обратите внимание, что свайп — это только часть преимущества.   -  person a_local_nobody    schedule 22.07.2019
comment
@a_local_nobody Я только что прочитал эту статью (кстати, спасибо), но я не совсем понимаю, как она может мне помочь, не могли бы вы объяснить мне, пожалуйста? (Я сказал, что я новичок ;) ).   -  person mathislr    schedule 22.07.2019
comment
нет проблем, так что один из способов обработки фрагментов и навигации — использовать просмотр пейджера (он позволяет вам перемещаться между фрагментами, но вы можете отключить это, если хотите). Затем вы даете своему пейджеру адаптер фрагментов. Этот адаптер фрагментов содержит только ОДИН экземпляр каждого фрагмента, затем вы можете указать пейджеру перейти на определенную страницу, в зависимости от действий пользователя, и он перейдет к этому экземпляру фрагмента.   -  person a_local_nobody    schedule 22.07.2019
comment
О, это звучит очень полезно в моем случае, я собираюсь прочитать некоторые документы и учебники и переработать свой код, большое спасибо!!   -  person mathislr    schedule 22.07.2019
comment
нет проблем, я постараюсь дать вам код через час или два, когда вернусь домой :P   -  person a_local_nobody    schedule 22.07.2019
comment
@a_local_nobody Мне было интересно, может ли Viewpager сочетаться с нижнимNavigationView?   -  person mathislr    schedule 22.07.2019
comment
да, они отлично работают вместе   -  person a_local_nobody    schedule 22.07.2019
comment
это просто немного усложнит вам жизнь, вам придется вручную обрабатывать навигацию, но это работает   -  person a_local_nobody    schedule 22.07.2019
comment
@a_local_nobody Большое спасибо за ваше терпение и объяснения. Благодаря вам я узнал довольно важный аспект программирования для Android. Ваше решение может быть отличным, но я думаю, что это займет у меня много времени. Знаете ли вы, можно ли просто изменить поведение по умолчанию popBackStackImmediate(string, int flags), чтобы избежать удаления стеков в backStack?   -  person mathislr    schedule 22.07.2019
comment
@a_local_nobody Я внес изменения, чтобы реализовать viewPager, но теперь я не знаю, как добавить фрагменты в задний стек, потому что транзакция больше не выполняется.   -  person mathislr    schedule 22.07.2019
comment
на сегодня я закончил помогать, мне нужно немного поспать, я вернусь к вам завтра, попробуйте взглянуть на это stackoverflow.com/questions/14368242 /   -  person a_local_nobody    schedule 22.07.2019
comment
Да, это не проблема :), в любом случае спасибо за ссылку *   -  person mathislr    schedule 22.07.2019


Ответы (1)


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

 private fun loadFragment(fragment: Fragment, previousFragment: Fragment?) {

    val transaction = supportFragmentManager.beginTransaction()
 if (supportFragmentManager.findFragmentByTag(fragment::class.java.simpleName) != null) {
        if (previousFragment != null) {
            transaction.hide(previousFragment).show(fragment).commit()
        } else {
            transaction.show(fragment).commit()
        }
    } else {

        if (previousFragment != null) {
            transaction.hide(previousFragment).add(R.id.frame_container, fragment, fragment::class.java.simpleName).addToBackStack(null).commit()
        } else {
            transaction.add(R.id.frame_container, fragment, fragment::class.java.simpleName).addToBackStack(null).commit()
         }
    }
    [email protected] = fragment
  }
person Mohan Sai Manthri    schedule 22.07.2019
comment
привет, спасибо за ваш ответ, но он не удаляет фрагмент в backStack ^^. Все равно спасибо - person mathislr; 22.07.2019
comment
Или, может быть, я не понял ваш код, потому что он написан на Котлине, а я этого языка не знаю ^^. - person mathislr; 22.07.2019
comment
Привет @mathislr, в приведенном выше коде мы добавим фрагмент только в том случае, если его не было в заднем стеке, иначе мы просто скроем предыдущий фрагмент и покажем текущий фрагмент. Он был протестирован и работает, я использовал это в очень многих проектах, если есть какие-либо проблемы, пожалуйста, оставьте их в разделе комментариев, я обязательно постараюсь решить проблему как можно скорее. - person Mohan Sai Manthri; 24.07.2019
comment
Этот код написан на котлине, не так ли? Потому что я не знаю, что такое val и fun... Я лично программирую на java, в любом случае спасибо, что уделили мне время :) - person mathislr; 24.07.2019