Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

popBackStack and commitAllowingStateLoss

Tags:

android

I call popBackStack() in Activity onCreate() method, however I am getting the exception:

Caused by java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

android.app.FragmentManagerImpl.checkStateLoss (FragmentManager.java:1428)
android.app.FragmentManagerImpl.enqueueAction (FragmentManager.java:1446)
android.app.FragmentManagerImpl.popBackStack (FragmentManager.java:572)

I understand that one way of solving this exception, provided you are OK with the effects on the UI and end user, is to call commitAllowingStateLoss.

The problem is, with popBackStack there is no commit call. Is there some other way to call popBackStack and allow state loss?

I should say, I am doing this in onPostResume and getting this exception.

like image 476
user3690202 Avatar asked Feb 28 '17 02:02

user3690202


People also ask

What is popBackStack?

public abstract void popBackStack () Pop the top state off the back stack. This function is asynchronous -- it enqueues the request to pop, but the action will not be performed until the application returns to its event loop.

What is commitAllowingStateLoss?

commitAllowingStateLoss():A transaction can only be committed with this method prior to its containing activity saving its state. If the commit is attempted after that point, an exception will be thrown. This is because the state after the commit can be lost if the activity needs to be restored from its state.

What is Android commitAllowingStateLoss?

commitAllowingStateLoss() Like commit() but allows the commit to be executed after an activity's state is saved.

Does popBackStack destroy fragment?

popBackStack will just revert your last FragmentTransaction . If you use FragmentTransaction. add , popBackStack will just call FragmentTransacetion.


1 Answers

After much research I have come to the conclusion that it is not possible to manipulate fragments on Android when the Activity is resumed. I have tried, as per the mentioned blog post, onPostResume() and onResumeFragments() to pop fragments from the backstack, and both result in intermittent crashes when released to production.

The downside to this reality is that if you wanted to, for example, display an end of level fragment, followed by an interstitial advertisement, followed by the next level (as a different fragment to the end of level fragment) then it is not possible to use fragments.

For my personal situation, I removed all fragments from my application. I keep using layouts, because editing the UI in XML is useful, but the Fragment lifecycle is unusable in its current state so I rolled my own "fragment" subsystem, but better because it can be manipulated from the Activities onResume.

I hope that one day Google will fix this because it makes developing for Android really unpleasant. Anyway, if anyone needs to use fragments, but doesn't like the typical onSaveInstanceState exception that you will invariably get, here is my "GameScreen" implementation (it's like a fragment, only better)

/**
 * GameScreen
 */
public class GameScreen {

    private int id;
    private View view;
    private ViewGroup viewGroup;
    protected MainActivity mainActivity;

    public GameScreen(MainActivity mainActivity, int id) {
        this.mainActivity = mainActivity;
        this.id = id;
    }

    public void create(LayoutInflater layoutInflater, ViewGroup viewGroup) {
        this.viewGroup = viewGroup;
        view = layoutInflater.inflate(id, viewGroup, false);
        viewGroup.addView(view);
    }

    public void show() {
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View v = viewGroup.getChildAt(i);
            if (v != view) {
                v.setVisibility(View.INVISIBLE);
            }
        }

        view.setVisibility(View.VISIBLE);
    }
}
like image 167
user3690202 Avatar answered Sep 20 '22 15:09

user3690202