получить последний фрагмент в backstack - PullRequest
92 голосов
/ 14 марта 2012

Как я могу получить последний экземпляр фрагмента, добавленный в backstack (если я не знаю тег фрагмента и идентификатор)?

FragmentManager fragManager = activity.getSupportFragmentManager();
FragmentTransaction fragTransacion = fragMgr.beginTransaction();

/****After add , replace fragments 
  (some of the fragments are add to backstack , some are not)***/

//HERE, How can I get the latest added fragment from backstack ??

Ответы [ 14 ]

1 голос
/ 28 мая 2019

Котлин

activity.supportFragmentManager.fragments.last()
1 голос
/ 12 февраля 2016

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

Если вы действительно хотите иметь стекфрагментов и чтобы иметь возможность доступа к фрагменту по его индексу в стеке, вам лучше иметь уровень абстракции над 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.

0 голосов
/ 13 сентября 2017

Самый высокий ответ (Дипак Гоэль) не сработал для меня. Каким-то образом тег не был добавлен должным образом.

В итоге я просто отправил идентификатор фрагмента через поток (используя намерения) и получил его непосредственно из менеджера фрагментов.

0 голосов
/ 03 ноября 2014

Или вы можете просто добавить тег при добавлении фрагментов, соответствующих их содержимому, и использовать простое статическое поле String (также вы можете сохранить его в пакете экземпляра действия в методе onSaveInstanceState (Bundle)), чтобы сохранить последний добавленный тег фрагмента и получить этот фрагментbyTag () в любое время, когда вам нужно ...

...