How to restore fragment back stack with in an activity (After application is killed in background)
Asked Answered
S

4

16

In an Android app-

Say I am in an Activity - MyActivity which holds one Fragment at a time.

First I loaded Fragment A to it (With no tags I added it to back stack of the FragmentManager)

Then at some point I loaded Fragment B (Again with no tags I added it to back stack of the FragmentManager)

Then at some point i loaded Fragment C (Again with no tags I added it to back stack of the FragmentManager)

I am using popBackStack() to enable back button behavior so whenever I press back from Fragment C the flow is like:

Fragment C -> Fragment B -> Fragment A -> Close MyActivity..

Everything is perfect :-)

But if I am in Fragment C and the app gets killed in background (I used "do not keep activity flag" from Settings)

and come back online Fragment C is loaded in MyActivity

but the FragmentManager's back stack contains only Fragment C..

The Back button is messing it up

Fragment C -> Close MyActivity..

Why is it so?

How to properly restore FragmentManager's back stack within an Activity?

Slum answered 19/2, 2016 at 4:25 Comment(6)
which is might because your activity is killed and it lost all its references if you want to you can create your own back stack and store some where in preferences and every time check if there is any thing in activity back stack if yes then remove (and remove from your back stack as well) if your activity back stack doesn't content then go as per your preferenceFazio
@VishalMokal Thanks for the input. back stack of an activity is managed by fragment manager. which means there is more than one way to add or remove fragments to back stack. Also this kind of a solution will not scale for a bigger application. As am also depending on fragments for navigation, a more fundamental solution is preferred.Slum
What do you mean with "I am using popBackStack to enable back button behavior" ? Does the Android system not automatically manage back button behavior if you add your fragments with fragmentTransaction.begin().add(fragment).addToBackStack().commit() ?Steed
post some code of how you add fragments and how you remove them (ex. have you a onBackPressed method?)Cascade
hello can you please put your code here..?Eldred
I will be posting code sample soonSlum
T
12

Try using alwaysRetainTaskState on your root activity. Android automatically clears the Activity backstack because it assumes that it has been a long time since you used the app and that the user wants to start again from the start.

 <activity android:alwaysRetainTaskState="true"/>

This setting will prevent that behaviour and it may follow that the behaviour is inherited by the Fragment Manager.

Tieback answered 29/2, 2016 at 10:10 Comment(2)
This flag is applicable at activity level onlySlum
Not working, still backstack will get empty when app killed and open using notification.Antimacassar
G
6

While developing your app, I recommend you to test restore/saved states of the activities, fragments with ADB:

  1. Open app
  2. Navigate between activities
  3. Press home
  4. ADB -> Kill (stop) app
  5. Press the application stack (menu button from the device) and resume the application

This way you can debug the saved/restore states.

If you don't have a complex application, I suggest you to handle the saved/restore state in the activity:

private Fragment1 mFragment;

@Override
protected void onCreate(Bundle savedState) {
   super.onCreate(savedState);
   // ...

   if (savedState == null) {
       mFragment = new Fragment1();

       getFragmentManger().beginTransacation().add(mFragment, TAG).addToBackStack(TAG).commit();
   }
   else {
       mFragment = getFragmentMananager().findFragmentByTag(TAG);
   }
}

If you have several Fragments or a ViewPager or nested fragments, then things can get really complicated. I suggest you to restart the whole application:

@Override
protected void onCreate(Bundle savedState) {
   super.onCreate(savedState);

   if (savedState != null) {
      Intent intent = new Intent(ActivityMain.this, ActivityMain.class);
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
      startActivity(intent);

      return;
   }
}

If you want to handle each saved/restore state, please read this post: http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

Garderobe answered 29/2, 2016 at 12:56 Comment(1)
I agree, the second solution (restart activity) is a quick warkaround if your root activity is the one that's hosting the fragments, thank youCranmer
C
1

try this method

public void setRetainInstance (boolean retain)

Control whether a fragment instance is retained across Activity re-creation (such as from a configuration change). This can only be used with fragments not in the back stack. If set, the fragment lifecycle will be slightly different when an activity is recreated:

from developer website http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance%28boolean%29

Coburn answered 4/3, 2016 at 6:2 Comment(0)
A
0

Fragment C should never be loaded after your application dies. Do you have an Init Fragment in your application ? Ideally when you are implementing a pop of fragments there should be an Init screen. If the application dies or is killed for memory reasons you application should start from Fragment A (Init Fragment). Not from Fragment C.

If your problem demands this solution, then you should have to save each fragment persistently when a new fragment come on top. Which ideally means you are persisting your backstack in a preference or a database to achieve this.

Anatole answered 4/3, 2016 at 9:33 Comment(4)
Super.onCreate will load the last fragment when activity is recreated.. Also data loss is managed .. Thing that concerns is the order of fragmentSlum
Do you pass an object of savedInstance to onCreate ?Anatole
Yes am passing the sameSlum
If Fragment C is loading automatically this info would be in saved instances. You should use onSaveInstanceState() and onRestoreInstanceState(). You might get a fill description about it here: developer.android.com/training/basics/activity-lifecycle/… You should override onSaveInstanceState() and restore it when your activity is started again.Anatole

© 2022 - 2024 — McMap. All rights reserved.