The main idea of the fragment is to show the information that the user needs and let the activity do the logic the application needs.
Fragment Navigation
As the small intro suggest, a well maintained application should use fragments to show information to the user using a coherent navigation system. If you still use layouts over your Activity take a look on adding fragments and how do they attach.
Adding a fragment explained
The fragment has 2 main components: the XML resource that describes the view and the logical part, the Java code.
The xml resource is the visual, it's what we want the user to see. This layout is attached to the fragment when it's created.
After the XML attaches to the logical part, the fragment itself attaches to the Activity containing both visual and logical part.
![]() |
Caption this |
When it's needed, the fragment can update the contents of its own layout to display the information you need from the methods that a fragment class has, but the navigation is not so simple.
To attach a fragment, the Holder Activity has to use a Fragment Manager and call for the add or replace methods to paint a fragment.
...
//This will add a fragment
getFragmentManager().add(...).commit();
...
//This also adds a fragment
getFragmentManager().replace(...).commit();
...
With the help of the fragment manager, you can add or replace a fragment.
Add a fragment
When adding a fragment, the add() method from the Fragment Manager adds a fragment to the Activity layout. As you may know, you need to provide the layout id where its going to be placed. The important thing here is that the fragment will stack on this layout no matter if there was already a fragment on it. Because of that, you should use add() for the very first fragment in your app, your Home Screen if you will. Since it won't stop any previous fragment running, this method will keep all of the fragments brought to the layout alive, consuming more memory than replacing them.
Replace a fragment
When a fragment is replaced with replace() it will stop any fragment already running in the given layout and it will then add the new fragment. This is ideal when moving to a new screen or step.
Now that you understand add() and replace() you can implement your navigation design with a new method from the Fragment Manager: the addToBackStack().
Backstack Trace
The BackStackTrace is a trace where the Fragment Manager keeps a record of the fragments that an Activity attaches. This is extremely important to understand because since you are working with a single Activity your app will exit if you press the Back button in Android or navigate to a previous Activity if there is one. This means that you could guide the user to a 3 different fragments inside your app, but when he / she press the back button he / she would expect to see the previous screen but instead the app will exit.
With the stack trace, the Fragment Manager will catch the back event and it will dettach the current fragment and will attach the lastest fragment added to the stack preventing the Activity to stop instead. This will always happen if there is at least 1 remaining fragment in the stack. When there are no fragments in the stack the Activity will handle the back event.
Add a fragment to the stack
Using the Fragment Manager you can call addToBackStack() before adding the fragement.
...
//This will add a fragment and will add it to the backstack trace
getFragmentManager().add(...).addToBackStack().commit();
...
//This will replace a fragment and will add it to the backstack trace
getFragmentManager().replace().addToBackStack().commit();
...
Now don't get confused. The fragment that makes it into the stack is the current fragment, which makes sense because when you press back in the new fragment, you will go back to the previous one.
This means that the list in the backstack has a first in, last out method; when a fragment adds it will move all of the already saved fragments and will stay on top. When the back button is pressed the trace "pops" and the lastest to enter will be the first one to show. Take a look to the following example.
Activity starts from the begginig. Let's add a fragment.
...
//Remember, use add() only for the first fragment
getFragmentManager().add(...).commit();
//No backstack trace yet, press back from the home screen and the activity ends
...
Let's move to a new screen by adding a new fragment
//Remember, use replace() to move between fragments
getFragmentManager().replace(...).
addToBackStack(null).commit(); //Don't worry with the null parameter, it will work just fine like that
//The current fragment is now the only element in the backstack.
...
![]() |
Now the first fragment is in the backstack and the second fragment is on screen |
As the code says, the current fragment is stopped and replaced with the new one but its trace is saved in the backstack. This means that when the user presses back, the old fragment will show up replacing the new fragment.
![]() |
When the user press "Back" the backstack will "pop" it's lastest element and put it into the screen |
Let's pretend that the user never presses back and it moves from the second fragment to a third one.
//Remember, use replace() to move between fragments
getFragmentManager().replace(...).
addToBackStack(getFragmentManager().getFragment().getTag()).commit();
//There are now 2 fragments in the backstack.
...
This means that when the user presses back from the third fragment, the stack will pop and bring the second fragment to screen, now there will be remaing the first fragment in the backstack. As you could guess the user could move from this point (the second fragment) again to a new fragment, the remaining trace in the backstack will move 1 step deeper and the current fragment will leave a trace in the backstack on the top of it. If the user goes back, it will go again to the second fragment and the first fragment will remain in the trace.
Adding complexity to the backstack
Now that you understand how does the backstack works, you could implement a much more complex design. For example, what if you want to skip a fragment between 2 when going back? Start from A, go to B, navigate to C and go back from C to A.
1) Add fragment A and don't add it to the stack trace (There is nothing behind it, the app should exit when back is pressed)
getFragmentManager().add(...).commit();
2) Replace fragment A with fragment B but now add to the backstack trace. Remember, you are adding rhe current frag,ment, not the new one.
getFragmentManager().replace(...).
addToBackStack(getFragmentManager().getFragment().getTag()).commit();
3) Replace fragment B with fragment C. Don't add anything else to the stack.
getFragmentManager().replace()..commit();

Now, from fragment C, when going back, the fragment manager goes to the backstack trace and "pops" the lastest fragment on it. As you could imagine, the only fragment there is fragment A therefore you would go to fragment A instead of fragment B.
![]() |
Second fragment is skipped because there was no such trace on the backstack |
You could also clear the entire stack and add a new one. Like when the user ends some steps for a configuration and you want to take him / her to the Home Screen without having the chance to going back to all of those already used screens.
One thing you could try is to manually pop all of the fragments in the backstack trace.
for (int i=0; i<getFragmentManager().getBackStackEntryCount(); ++i){
getFragmentManager().popBackStack();
}
And after add the fragment like it was the very first one added (No backstack trace added).
Like this link on stackoverflow.com suggest, you can also do the followin for the same result
getFragmentManager().popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Now you know all you need to create an effective fragment navigation design. If you have any doubt or you want to share an idea on this topic please feel free to do it and share it with the rest of developers.
Than you for reading
No comments:
Post a Comment