Подтвердить что ты не робот

Фрагмент стоп-кадра Android

У меня есть несколько страниц/фрагментов, перечисленных в моем навигационном ящике, пользователь, вероятно, будет переключаться между ними часто, и я хочу, чтобы они были в backstack, чтобы они могли перемещаться назад, но мне нужен только один экземпляр каждого фрагмента в backstack, так что пользователю не нужно нажимать безумное количество раз, чтобы выйти из приложения. Я не могу понять, как эффективно "переупорядочить" стопку "без удаления страниц.

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

  if (mFragMgr == null) {
      mFragMgr = getSupportFragmentManager();
  }

  String backStateName = fragmentDescriptor.name();
  boolean fragmentPopped = mFragMgr.popBackStackImmediate(backStateName, 0);
  if (!fragmentPopped){
      mFragMgr.beginTransaction()
      .remove((Fragment) mFragment)
      .replace(R.id.content_frame, (Fragment) mFragment)
      .addToBackStack(backStateName)
      .commit();
  }

Я использую этот код в onBackPressed

  @Override
  public void onBackPressed() {
      if (mFragMgr.getBackStackEntryCount() > 0) {
          mFragMgr.popBackStackImmediate();
      } else {
          super.onBackPressed();
      }
  }

Это работает, но это означает, что он удаляет страницы, которые я не хочу удалить. Пример:

Когда мой пользователь посещает 6 страниц в порядке A > B > C > D > E > C, потому что я делаю удаление, я ожидал следующий стек:

                            [E]    [C]
                     [D]    [D]    [E]
              [C]    [C]    [C]    [D]
       [B]    [B]    [B]    [B]    [B]
[A] -> [A] -> [A] -> [A] -> [A] -> [A]

Но то, что я на самом деле получаю, следующее: оно всплывает до элемента, который соответствует имени, это независимо от того, включаю ли я ".remove((Fragment) mFragment)" или нет - (я уже теперь понял, что удаление не влияет на backstack, поэтому не нужно указывать на это):

                            [E]
                     [D]    [D]
              [C]    [C]    [C]    [C]
       [B]    [B]    [B]    [B]    [B]
[A] -> [A] -> [A] -> [A] -> [A] -> [A]

Если я не использую имя и вместо этого использую null при добавлении в backstack, я получаю следующее:

                                   [C]
                            [E]    [E]   
                     [D]    [D]    [D]    
              [C]    [C]    [C]    [C]   
       [B]    [B]    [B]    [B]    [B]  
[A] -> [A] -> [A] -> [A] -> [A] -> [A] 

Как я могу получить поведение, которое я ожидаю? Возможно ли вообще, или мне придется записывать изменения самостоятельно и вообще пропускать заднюю часть?

4b9b3361

Ответ 1

Нет никакого API, чтобы это сделать, но, поскольку я интересовался тем же самым делом на прошлой неделе,
Я воспринял это как упражнение, осуществив его сам.

Мой метод позволяет удалить Fragment из любого места в backstack, и это достигается за счет использования refrection для изменения внутренних переменных, которые хранят данные backstack в FragmentManagerImpl и BackStackRecord.

Существует несколько важных переменных:

  • mBackStack - хранит BackStackRecord, в котором хранятся данные Fragment, предыдущие, анимации и т.д.
  • mActive - все добавленные Fragment s
  • mAvailBackStackIndices - хранит индексы, которые могут использоваться вновь вставленными записями, то есть индексы значений null в mActive
  • и другие

Протестировано с помощью 150 + Fragment и не заметил никаких утечек, но только отслеживал кучу в DDMS и не выполнял никакого другого анализа памяти.
Так как someting может быть сломан, исследовать код, перепроверить его, посмотреть, дает ли кто-нибудь лучший ответ и переосмыслить, действительно ли вам нужно сделать это в своем проекте.

Я загрузил код как gist на GitHub, надеюсь, что это поможет.

Ответ 2

Если вы хотите повторно использовать фрагмент перед ним, сначала скройте все фрагменты и покажите желаемый фрагмент за раз. Делая это, вы можете повторно использовать свои фрагменты, не удаляя их и не перезагружая фрагменты. Но перед тем, как реализовать его, вы должны добавить фрагмент в backstack.