'Refresh fragment is not working any more?

I lost some hours today because my code was not working any more. The code to reload the view of a fragment was not working anymore after updating to the new version of Support Library 25.1.0:

This is my code :

FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = manager.beginTransaction();
fragmentTransaction.detach(fragment);
fragmentTransaction.attach(fragment);
fragmentTransaction.commit();

I have tried to debug putting some breakpoints on

public void onPause()
public void onStop()
public void onAttach(Context context)
public void onDetach()  
public void onDestroyView()
public void onDestroy()

but the application is not entering into any of that function and nothing happened on the screen.

If I call detach alone, without attach, the application enter in onPause and onStop and the view leave the screen.



Solution 1:[1]

I've found myself facing the same issue, and found no answer online. Finally I've found out that some optimizations were added to Fragment Transactions in Revision 25.1.1 of the Support Library. (see https://developer.android.com/topic/libraries/support-library/revisions.html#25-1-1). Disabling those for your transaction will make it work as expected:

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setAllowOptimization(false);
transaction.detach(fragment).attach(fragment).commitAllowingStateLoss();

Update

setAllowOptimization is deprecated. Use setReorderingAllowed instead.

Solution 2:[2]

Faced a similar issue after updating androidx.navigation from 2.3.1 to 2.3.2.

parentFragmentManager.beginTransaction().detach(this).attach(this).commit()

has stopped reload the view of a fragment. Everything that I found here did not help, but I noticed that separately the detach and attach operations are being performed successfully, I decided to spread their execution to different FragmentTransaction entities:

parentFragmentManager.beginTransaction().detach(this).commit ()
parentFragmentManager.beginTransaction().attach(this).commit ()

and it worked. Hope this saves someone some time.

Solution 3:[3]

@Viad actually answered the question. To add a little bit to it, this happens in android versions 26 and above where reordering is allowed by default. Reordering comes into play when two fragment operations are requested at the same done, for example adding fragment 1 and then replacing it with fragment 2, which causes only the latter (replacing fragment 2) to happen.

So when reordering is allowed by default, when restarting the fragment using detach(fragment).attach(fragment) the first one is ignored and only second one is executed. As the fragment is already attached, attach(fragment) does not do anything. This is why none of the lifecycle methods of the fragment is called.

The resolution to the problem would be to setReorderingAllowed(false) to deactivate reordering. So the solution would be:

                    FragmentTransaction transaction = mActivity.getFragmentManager()
                            .beginTransaction();
                    if (Build.VERSION.SDK_INT >= 26) {
                        transaction.setReorderingAllowed(false);
                    }
                    transaction.detach(fragment).attach
                            (fragment).commit();

Solution 4:[4]

Here is a slight modification I made to use getSupportFragmentManager:

FragmentTransaction t = getActivity().getSupportFragmentManager().beginTransaction();
t.setAllowOptimization(false);
t.detach(this).attach(this).commitAllowingStateLoss();

Solution 5:[5]

To achieve the fragment's refresh with Androidx is a bit different.

As per Android Developers documentation here

As a FragmentTransaction is treated as a single atomic set of operations, calls to both detach and attach on the same fragment instance in the same transaction effectively cancel each other out, thus avoiding the destruction and immediate recreation of the fragment's UI. Use separate transactions, separated by executePendingOperations() if using commit(), if you want to detach and then immediately re-attach a fragment.

Therefore the code must be like this :

fun FragmentActivity.relaunchFragment(fragmentId: Int) {
val currentFragment = supportFragmentManager.findFragmentById(fragmentId)
val detachTransaction = supportFragmentManager.beginTransaction()
val attachTransaction = supportFragmentManager.beginTransaction()

currentFragment?.let {
    detachTransaction.detach(it)
    attachTransaction.attach(it)
    detachTransaction.commit()
    attachTransaction.commit()
}

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Aba
Solution 2 Johann Stolz
Solution 3
Solution 4 M--
Solution 5 shady31