Android peek backstack without popping

1.3k views Asked by At

For my application, some fragments require the user to enter a pin in a dialog before it is shown. I have a BaseFragment class that all my other fragments extend which stores if the pin is required. My issue right now is dealing with the back button as if the user tries to go back to a fragment that requires the pin it needs to show a pin dialog first.

Currently I'm overriding onBackPressed() in which I want to peek the backstack to see what fragment will be resumed if popBackstack() was called so I can check if the pin dialog should be shown. Below is my current code which popFragment is coming back null:

@Override
public void onBackPressed() {
    if(getSupportFragmentManager().findFragmentById(R.id.fragment_container) instanceof BaseFragment) {
        BaseFragment frag = (BaseFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_container);

        if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
            int index = getSupportFragmentManager().getBackStackEntryCount() - 1;
            Log.e("Back stack", Integer.toString(index));
            FragmentManager.BackStackEntry backEntry = (FragmentManager.BackStackEntry) getSupportFragmentManager().getBackStackEntryAt(index);

            BaseFragment popFragment = (BaseFragment) getSupportFragmentManager().findFragmentById(backEntry.getId());

            BaseFragment.checkAuth(this, frag, popFragment, new NavigationCallback((AppCompatActivity) this));
        } else {
            super.onBackPressed();
        }
    } else {
        super.onBackPressed();
    }
}

I've checked if backEntry is null and its not. backEntry.getId() also comes back with a value of 1 so I'm not sure why findFragmentById() is then null. I also dont think it has to do with how I'm showing fragments but here is my code for that as well:

FragmentManager fragManager = mActivity.getSupportFragmentManager();
FragmentTransaction transaction = fragManager.beginTransaction();
transaction.replace(R.id.fragment_container, mFragment);
transaction.addToBackStack(null);
transaction.commit();
2

There are 2 answers

3
kris larson On BEST ANSWER

The BackStackEntry id and Fragment id have nothing to do with each other.

I have done something similar to what you are doing by using tags. Again, the BackStackEntry tag and Fragment tags have nothing to do with each other; however, by using the same value for both tags you can accomplish your goal.

String tag = ...
FragmentManager fragManager = mActivity.getSupportFragmentManager();
FragmentTransaction transaction = fragManager.beginTransaction();
// tag is associated with fragment
transaction.replace(R.id.fragment_container, mFragment, tag);
// same tag is associated with back stack entry
transaction.addToBackStack(tag);
transaction.commit();

...

int count = fragmentManager.getBackStackEntryCount();
if (count > 0) {
    FragmentManager.BackStackEntry topBackStackEntry = 
            fragmentManager.getBackStackEntryAt(count - 1);
    String tag = topBackStackEntry.getName();

    if (tag != null) {
        Fragment fragment = fragmentManager.findFragmentByTag(tag);
        if (fragment != null) {
            // we found the fragment
            // you can also sanity-check here with fragment.isResumed()
        }
    }
}
0
binrebin On

You are gone Frag-A -> Frag-B -> Frag-C. Now you want to go back to Frag-A without creating a new Fragment view for Frag-A ? Here is the solution:

Navigation.findNavController(requireView()).popBackStack(R.id.Frag_A, false)

Also delete your nav entry action_Frag_C_to_Frag_A. If you have accidentely created a navgraph.