Refresh fragment is not working any more?
Asked Answered
O

5

13

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.

Oca answered 21/12, 2016 at 19:51 Comment(3)
You should separate this into a question and then answer your own question. Don't put the question and answer together, it's confusing.Scarce
Thanks! After some time you should be able to mark it as the accepted answer.Scarce
@AidaIsay : nop, I just revert back to library support revision 25.0.1Oca
M
10

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.

Meiny answered 14/2, 2017 at 9:59 Comment(2)
Why do you suggest using commitAllowingStateLoss instead of just commit?Iinde
This doesn't work. Test it if you plan to use it.Punic
O
18

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.

Odontalgia answered 16/12, 2020 at 12:29 Comment(1)
None of the other solutions worked for me except this. Truly saved my time. Thanks a lotFrore
M
10

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.

Meiny answered 14/2, 2017 at 9:59 Comment(2)
Why do you suggest using commitAllowingStateLoss instead of just commit?Iinde
This doesn't work. Test it if you plan to use it.Punic
D
6

@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();
Droll answered 13/7, 2018 at 14:28 Comment(1)
The issue with the SDK version > 25 made me crazy, thank you!Paisano
T
2

Here is a slight modification I made to use getSupportFragmentManager:

FragmentTransaction t = getActivity().getSupportFragmentManager().beginTransaction();
t.setAllowOptimization(false);
t.detach(this).attach(this).commitAllowingStateLoss();
Tarmac answered 17/4, 2017 at 21:25 Comment(0)
K
2

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()
    }
}
Kierakieran answered 10/7, 2021 at 21:7 Comment(1)
What is executePendingOperations? There's no executePendingOperations in your codeMischief

© 2022 - 2024 — McMap. All rights reserved.