Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment backstack bug when replacing fragments in a transaction?

Here's the scenario that causes problems:

  1. I start an Acitivity with a ViewGroup that'll hold the presented fragments.
  2. I load Fragment A into this ViewGroup by calling .replace() in the transaction that I save onto the backstack.
  3. I load Fragment B into the Viewgroup, replacing Fragment A. Again, I save the transaction.
  4. I rotate the device twice.
  5. On the second rotation, Fragment A (which is not visible at the moment) will throw a NullPointer exception.

This exception is thrown by Fragment A, because I'm saving some values of Views (EditTexts e.g.) in its onSaveInstanceState() method. It seems, that on the second rotation, the system doesn't instantiate these Views, so when I'm asking their values, I get a NullPointer exception. Can this be avoided somehow? Or is using .replace operations in a fragment transcation saved onto the backstack unadvised?

like image 856
Zsombor Erdődy-Nagy Avatar asked Nov 24 '11 17:11

Zsombor Erdődy-Nagy


People also ask

How do fragment transactions get added to the Backstack?

For more information on navigating with animations and transitions, see Fragment transactions and Navigate between fragments using animations. Calling addToBackStack() commits the transaction to the back stack. The user can later reverse the transaction and bring back the previous fragment by pressing the Back button.

How do I remove a fragment from a Backstack if already exists?

How do you delete Backstacks on Android? Use finishAffinity() to clear all backstack with existing one. Suppose, Activities A, B and C are in stack, and finishAffinity(); is called in Activity C, – Activity B will be finished / removing from stack. – Activity A will be finished / removing from stack.

How do you resume an existing Backstack fragment?

Since you want only one back stack entry per Fragment , make the back state name the Fragment's class name (via getClass(). getName() ). Then when replacing a Fragment , use the popBackStackImmediate() method. If it returns true, it means there is an instance of the Fragment in the back stack.

How do you adding removing and replacing fragments?

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();


1 Answers

I've had this but can't quite recollect the specifics of what I did to fix but generally speaking (and apologies for the brain dump) I do the following:

  1. Call setRetainInstance(true) in onCreate to avoid fragment recreation

  2. Save the state of edit controls etc. in onSaveInstanceState to be used if activity is killed and you get restored with a non-null bundle (you shouldn't get a non-null bundle on an orientation change with 1.)

  3. Maintain edit control values in member variables (as the fragment is not going to be recreated) ensuring they get updated in an onDestroyView from the edit controls and then use them to restore the edit control values in onCreateView

  4. Have a flag which I set to true in onCreateView and false in onDestroyView and ensure I don't touch UI controls when the view is not around.

BTW Using replace while adding the transaction to the back stack is perfectly OK.

Hope there's something in there that helps. Peter.

like image 100
PJL Avatar answered Nov 14 '22 23:11

PJL