Насправді до стеку не доданий останній фрагмент, тому що ви можете додати кілька або фрагментів до стеку за одну транзакцію або просто видалити фрагменти без додавання нового.
Якщо ви дійсно хочете мати стопку фрагментів і мати можливість отримати доступ до фрагменту за його індексом у стеці, вам краще мати шар абстракції над FragmentManager
та його backstack. Ось як це можна зробити:
public class FragmentStackManager {
private final FragmentManager fragmentManager;
private final int containerId;
private final List<Fragment> fragments = new ArrayList<>();
public FragmentStackManager(final FragmentManager fragmentManager,
final int containerId) {
this.fragmentManager = fragmentManager;
this.containerId = containerId;
}
public Parcelable saveState() {
final Bundle state = new Bundle(fragments.size());
for (int i = 0, count = fragments.size(); i < count; ++i) {
fragmentManager.putFragment(state, Integer.toString(i), fragments.get(i));
}
return state;
}
public void restoreState(final Parcelable state) {
if (state instanceof Bundle) {
final Bundle bundle = (Bundle) state;
int index = 0;
while (true) {
final Fragment fragment =
fragmentManager.getFragment(bundle, Integer.toString(index));
if (fragment == null) {
break;
}
fragments.add(fragment);
index += 1;
}
}
}
public void replace(final Fragment fragment) {
fragmentManager.popBackStackImmediate(
null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentManager.beginTransaction()
.replace(containerId, fragment)
.addToBackStack(null)
.commit();
fragmentManager.executePendingTransactions();
fragments.clear();
fragments.add(fragment);
}
public void push(final Fragment fragment) {
fragmentManager
.beginTransaction()
.replace(containerId, fragment)
.addToBackStack(null)
.commit();
fragmentManager.executePendingTransactions();
fragments.add(fragment);
}
public boolean pop() {
if (isEmpty()) {
return false;
}
fragmentManager.popBackStackImmediate();
fragments.remove(fragments.size() - 1);
return true;
}
public boolean isEmpty() {
return fragments.isEmpty();
}
public int size() {
return fragments.size();
}
public Fragment getFragment(final int index) {
return fragments.get(index);
}
}
Тепер замість додавання і видалення фрагментів шляхом виклику FragmentManager
безпосередньо, ви повинні використовувати push()
, replace()
і pop()
методи FragmentStackManager
. І ви зможете отримати доступ до найвищого фрагмента, просто зателефонувавши stack.get(stack.size() - 1)
.
Але якщо вам подобаються хаки, я маю інші способи робити подібні речі. Єдине, що я мушу зазначити, це те, що ці хаки працюватимуть лише з фрагментами підтримки.
Перший хак - це просто отримати всі активні фрагменти, додані до менеджера фрагментів. Якщо ви просто заміните фрагменти один за одним і виведете зі стека, цей метод поверне найвищий фрагмент:
public class BackStackHelper {
public static List<Fragment> getTopFragments(
final FragmentManager fragmentManager) {
final List<Fragment> fragments = fragmentManager.getFragments();
final List<Fragment> topFragments = new ArrayList<>();
for (final Fragment fragment : fragments) {
if (fragment != null && fragment.isResumed()) {
topFragments.add(fragment);
}
}
return topFragments;
}
}
Другий підхід є подій більш хакітним і дозволяє отримати всі фрагменти, додані в останній транзакції, для якої addToBackStack
було викликано:
package android.support.v4.app;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class BackStackHelper {
public static List<Fragment> getTopFragments(
final FragmentManager fragmentManager) {
if (fragmentManager.getBackStackEntryCount() == 0) {
return Collections.emptyList();
}
final List<Fragment> fragments = new ArrayList<>();
final int count = fragmentManager.getBackStackEntryCount();
final BackStackRecord record =
(BackStackRecord) fragmentManager.getBackStackEntryAt(count - 1);
BackStackRecord.Op op = record.mHead;
while (op != null) {
switch (op.cmd) {
case BackStackRecord.OP_ADD:
case BackStackRecord.OP_REPLACE:
case BackStackRecord.OP_SHOW:
case BackStackRecord.OP_ATTACH:
fragments.add(op.fragment);
}
op = op.next;
}
return fragments;
}
}
Будь ласка, зауважте, що в цьому випадку ви повинні класти цей клас у android.support.v4.app
пакет.
FragmentTransaction.add(int containerViewId, Fragment fragment, String tag)
абоFragmentTransaction.replace(int containerViewId, Fragment fragment, String tag)
doc