Fragment's onResume() not called when popped from backstack
Asked Answered
L

8

34

Hi I am developing android application in which I am using I am using single Activity and 3 fragments. So consider I have 3 fragments A B C. When I switch from A to B, I am adding Fragment to backstack and simillar for B to C. Now when I click back from C it shows me B and similar for B to A as well.

But thing is that when I come from C to B or B to A, it's not calling onResume() or any other life cycle methods of Fragment.

What I want to do actually for every Fragment I have different title in ActionBar. So, in my code, when I move from A to B or B to c, I am changing activity title inside fragment. But when I click on back it not changing according to that.

What is the actual problem? Why after pop from backstack its not calling onResume() for my Fragment? How do I solve this problem? Need Help. Thank you.

Likely answered 16/10, 2013 at 5:36 Comment(1)
onResume() of the fragment is called only when the activity is resumed. So this wont help you. Even I'm facing similar issue right now. You can implement OnBackStackChangedListener and get the fragment name in the top of the stack and set the actionbar title based on that.Brick
B
26

onResume() of the Fragment is called only when the Activity is resumed. So this wont help you. Even I'm facing similar issue right now. You can implement OnBackStackChangedListener and get the fragment name in the top of the stack and set the ActionBar title based on that.

private FragmentManager.OnBackStackChangedListener getListener()
{
    FragmentManager.OnBackStackChangedListener result = new FragmentManager.OnBackStackChangedListener()
    {
        public void onBackStackChanged()
        {
            FragmentManager manager = getFragmentManager();

            if (manager != null)
            {
                if(manager.getBackStackEntryCount() >= 1){
                    String topOnStack = manager.getBackStackEntryAt(manager.getBackStackEntryCount()-1).getName();
                    Log.i("TOP ON BACK STACK",topOnStack);
                }
                }
            }
    };

    return result;
}
Brick answered 27/11, 2013 at 16:58 Comment(1)
This is what I'm using tooImidazole
C
16

Try to use the replace method instead add on the FragmentTransaction. This work for me:

FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, fragment);
ft.addToBackStack(null);
ft.commit();
Capuchin answered 27/11, 2013 at 15:34 Comment(3)
This works. Probably should now be the accepted answer.Lenient
The fragments <b>onResume()</b> or onPause() will be called only when the Activities onResume() or onPause() is called. They are tightly coupled to the Activity. if you call replace onStop() will called.Idealist
Replacing the fragment will recreate the UI and execute the business logic written in onCreateView and onViewCreated methods. Be careful before using this approach.Tradespeople
V
9

As others have said already, onResume() is only called when the activity itself is resumed, so that isn't going to help at all.

You need to check if you're adding a new fragment, or replacing an existing fragment in your fragment transaction:

  • If you replace() a previous fragment, that previous fragment will be recreated from scratch when you go back to it, so onCreateView() will be called again, and you can update your toolbar title there. You probably do already.

  • If you add() a new fragment, the previous fragment is still there, only not visible. When you go back to it, it's up to you to get the last entry from the back stack (use getBackStackEntryCount() and getBackStackEntryAt() in the fragment manager), get the corresponding Fragment object (use findFragmentByTag() in the fragment manager), cast that Fragment to some base class that all your fragments will inherit from, and call a custom method, e.g. onVisible(), on that fragment. The default implementation of onVisible() in your base class does nothing. Override in each fragment to update toolbar title, FAB, and anything else as required. I'm also calling onVisible() from onResume() to avoid code duplication.

Violinist answered 10/1, 2018 at 18:4 Comment(0)
M
4

you can use this method of fragment :

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
}
Mutter answered 18/7, 2018 at 20:30 Comment(1)
But when I pop up fragment from stack then it's not calling this.Interpolation
P
2

Put this code in your fragment.

@Override
public void setUserVisibleHint(boolean visible) {
        super.setUserVisibleHint(visible);
        if (visible && isResumed()) {
            onResume();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!getUserVisibleHint()) {
            return;
        }
        setData();
    }
Proteinase answered 2/2, 2017 at 6:18 Comment(0)
O
2

I use this way, add this block code in your fragment

requireActivity().supportFragmentManager.addOnBackStackChangedListener {
            val fm = requireActivity().supportFragmentManager
            fm?.let {
                if (it.backStackEntryCount == YOUR_FRAGMENT_BACK_STACK_INDEX) {
                    // your fragment visible
                }
            }
        }
Oestrone answered 31/7, 2019 at 9:28 Comment(1)
This is the Best answer. Trust me :)Spenserian
M
0

The other answers relied on a particular fragment transaction being named, or having a tagged fragment, relying on a deprecated method, or putting logic in the Activity. This detects the fragment's visibility on the back stack using its view, which for my needs this was close enough to an onResume. Since this is concerned with being on top of the back stack.

View extension to detect if a view is being displayed on the screen: (see also How can you tell if a View is visible on screen in Android?)

fun View.isVisibleOnScreen(): Boolean {
    if (!isShown) return false
    val actualPosition = Rect().also { getGlobalVisibleRect(it) }
    val screenWidth = Resources.getSystem().displayMetrics.widthPixels
    val screenHeight = Resources.getSystem().displayMetrics.heightPixels
    val screen = Rect(0, 0, screenWidth, screenHeight)
    return Rect.intersects(actualPosition, screen)
}

Then defined a back stack listener from the fragment, watching the top fragment on the stack (the one added last)

fun Fragment.setOnFragmentStackVisibilityListener(onVisible: () -> Unit) {
    val renderDelayMillis = 300L
    parentFragmentManager.addOnBackStackChangedListener {
        Handler(Looper.getMainLooper()).postDelayed({
            if (isAdded) {
                val topStackFragment = parentFragmentManager.fragments[parentFragmentManager.fragments.size - 1]
                if (topStackFragment.view == view && isVisible && view!!.isVisibleOnScreen()) {
                    onVisible.invoke()
                }
            }
        }, renderDelayMillis)
    }
}

The back stack listener is called before the view is ready so an arbitrarily small delay was needed.

Mell answered 26/8, 2021 at 0:41 Comment(0)
B
-1

Try to change title on onCreateView() of Fragment.

Bubaline answered 16/10, 2013 at 6:43 Comment(3)
But when I pop up fragment from stack then it's not calling any life cycle method. Then what should I. thank you for help.Likely
You need to change the title in onCreateView method of fragment. When you pop or add fragment to stack oncreateview method is called and then you set title according to your fragment class.Bubaline
@HarshitRathi I tried this and as @Likely said onCreateView() is not called when a fragment is popped from teh back stack and the new one becomes visible.Calysta

© 2022 - 2024 — McMap. All rights reserved.