Фрагмент стоп-кадра 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]
Как я могу получить поведение, которое я ожидаю? Возможно ли вообще, или мне придется записывать изменения самостоятельно и вообще пропускать заднюю часть?
Ответы
Ответ 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.