Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

hidden backstack fragments re-shown on configuration change

I am building a one activity-multiple fragments application. I add to the backstack after every transaction. After a couple of hiding and showing fragments and then I rotate the phone, all the fragments added on the container were restored and every fragment is on top of the other.

What can be the problem? Why is my activity showing the fragments I have previously hidden?

I am thinking of hiding all the previously-hidden-now-shown fragments but is there a more 'graceful' way of doing this?

like image 400
yojoannn Avatar asked Jun 22 '12 11:06

yojoannn


People also ask

How to change fragments android?

Use replace() to replace an existing fragment in a container with an instance of a new fragment class that you provide. Calling replace() is equivalent to calling remove() with a fragment in a container and adding a new fragment to that same container. transaction. commit();

How do you know if a fragment is recreated?

The simple answer to that would be call getData from onCreate() , but then I get nullPointer, because at that point I have no AsyncTask . So I need to somehow to know whether fragment was just have been created or it was just detached and then attached again.

How can I maintain fragment state when added to the back stack?

Solution: Save required information as an instance variable in calling activity. Then pass that instance variable into your fragment. So following on with my example: before I display F2 I save user data in the instance variable using a callback. Then I start F2, user fills in phone number and presses save.


1 Answers

Use setRetainInstance(true) on each fragment and your problem will disappear.
Warning: setting this to true will change the Fragments life-cycle.
While setRetainInstance(true) resolves the issue, there may be cases where you don't want to use it. To fix that, setup a boolean attribute on the Fragment and restore the visibility:

private boolean mVisible = true;
@Override
public void onCreate(Bundle _savedInstanceState) {
    super.onCreate(_savedInstanceState);
    if (_savedInstanceState!=null) {
        mVisible = _savedInstanceState.getBoolean("mVisible");
    }
    if (!mVisible) {
        getFragmentManager().beginTransaction().hide(this).commit();
    }
    // Hey! no setRetainInstance(true) used here.
}
@Override
public void onHiddenChanged(boolean _hidden) {
    super.onHiddenChanged(_hidden);
    mVisible = !_hidden;
}
@Override
public void onSaveInstanceState(Bundle _outState) {
    super.onSaveInstanceState(_outState);
    if (_outState!=null) {
        _outState.putBoolean("mVisible", mVisible);
    }
}

Once the configuration changes (e.g. screen orientation), the instance will be destroyed, but the Bundle will be stored and injected to the new Fragment instance.

like image 118
miguelt Avatar answered Oct 05 '22 23:10

miguelt