get the latest fragment in backstack

后端 未结 17 2041
长发绾君心
长发绾君心 2020-11-27 11:24

How can I get the latest fragment instance added in backstack (if I do not know the fragment tag & id)?

FragmentManager fragManager = activity.getSupport         


        
相关标签:
17条回答
  • 2020-11-27 11:41

    Actually there's no latest fragment added to the stack because you can add several or fragments to the stack in a single transaction or just remove fragments without adding a new one.

    If you really want to have a stack of fragments and to be able to access a fragment by its index in the stack, you'd better have an abstraction layer over the FragmentManager and its backstack. Here's how you can do it:

    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);
      }
    }
    

    Now instead of adding and removing fragments by calling FragmentManager directly, you should use push(), replace(), and pop() methods of FragmentStackManager. And you will be able to access the topmost fragment by just calling stack.get(stack.size() - 1).

    But if you like hacks, I have to other ways of doing similar things. The only thing I have to mention is that these hacks will work only with support fragments.

    The first hack is just to get all active fragments added to the fragment manager. If you just replace fragments one by one and pop the from the stack this method will return the topmost fragment:

    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;
      }
    }
    

    The second approach is event more hacky and allows you to get all fragments added in the last transaction for which addToBackStack has been called:

    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;
      }
    }
    

    Please notice that in this case you have to put this class into android.support.v4.app package.

    0 讨论(0)
  • 2020-11-27 11:44

    Looks like something has changed for the better, because code below works perfectly for me, but I didn't find it in already provided answers.

    Kotlin:

    supportFragmentManager.fragments[supportFragmentManager.fragments.size - 1]
    

    Java:

    getSupportFragmentManager().getFragments()
    .get(getSupportFragmentManager().getFragments().size() - 1)
    
    0 讨论(0)
  • 2020-11-27 11:47

    I personnaly tried many of those solutions and ended up with this working solution:

    Add this utility method that will be used several times below to get the number of fragments in your backstack:

    protected int getFragmentCount() {
        return getSupportFragmentManager().getBackStackEntryCount();
    }
    

    Then, when you add/replace your fragment using FragmentTransaction method, generate a unique tag to your fragment (e.g.: by using the number of fragments in your stack):

    getSupportFragmentManager().beginTransaction().add(yourContainerId, yourFragment, Integer.toString(getFragmentCount()));
    

    Finally, you can find any of your fragments in your backstack with this method:

    private Fragment getFragmentAt(int index) {
        return getFragmentCount() > 0 ? getSupportFragmentManager().findFragmentByTag(Integer.toString(index)) : null;
    }
    

    Therefore, fetching the top fragment in your backstack can be easily achieved by calling:

    protected Fragment getCurrentFragment() {
        return getFragmentAt(getFragmentCount() - 1);
    }
    

    Hope this helps!

    0 讨论(0)
  • 2020-11-27 11:48
    FragmentManager.findFragmentById(fragmentsContainerId) 
    

    function returns link to top Fragment in backstack. Usage example:

        fragmentManager.addOnBackStackChangedListener(new OnBackStackChangedListener() {
            @Override
            public void onBackStackChanged() {
                Fragment fr = fragmentManager.findFragmentById(R.id.fragmentsContainer);
                if(fr!=null){
                    Log.e("fragment=", fr.getClass().getSimpleName());
                }
            }
        });
    
    0 讨论(0)
  • 2020-11-27 11:48

    you can use getBackStackEntryAt(). In order to know how many entry the activity holds in the backstack you can use getBackStackEntryCount()

    int lastFragmentCount = getBackStackEntryCount() - 1;
    
    0 讨论(0)
  • 2020-11-27 11:49

    Keep your own back stack: myBackStack. As you Add a fragment to the FragmentManager, also add it to myBackStack. In onBackStackChanged() pop from myBackStack when its length is greater than getBackStackEntryCount.

    0 讨论(0)
提交回复
热议问题