Navigating Android Fragments with the Navigation Component
Tags: java, android, tristan
Published: 2021-07-07 23:57:44

#Introduction
- This series is going to be dedicated to the basic of Android development. Join me and let us try to build and understand some cool stuff. All the resources I used to create this post can be found on ticketnote or [HERE](https://ticketnote.dev/ticket/utdMW4ZLkNGHdKAgfwN8). 

###YouTube Version
- [HERE](https://www.youtube.com/watch?v=XsqBjfkoXoE)


###Getting started
- Before you read on I want to state some definitions and important information that will help you along the way

###Definitions 
- In this blog post there is going to see a lot of nav this and navigation that, it can get confusing. This section will act as as sort of appendix for the post. 

**Navigation Graph :** is a resource file that contains all of our destinations and actions. This graph represents all of our app's possible navigation paths.

**NavHost :** this is a very important interface and concept. The NavHost acts as an empty container where destinations are swapped in and out as the user navigates through the app. All navigation is done inside of a NavHost.

**NavHostFragment :** this is the default implementation of NavHost and is what is responsible for swapping between destinations. We will add this manually inside of a XML file.


**NavController :** the actual navigation is done through a NavController, inside of a NavHostFragment. Each NavHostFragment has its own NavController.

**Destinations :** navigation in our app occurs between destinations, meaning that anywhere out app can navigate is called a destination. Destinations are represented via fragments.

**Actions :** logical connections between our destinations that represent the paths our user can take. We use these actions to tell our app the proper navigation route.


###Important things to know
- The Navigation Component is a collection of libraries and tools that we have available to us. So anytime someone is talking about the Navigation Component they are not referencing a singular object or class but an entire collection.

- Navigation Component is designed for apps that have one main activity with multiple fragments. The main activity is associated with a navigation graph and contains a NavHostFragment that is responsible for swapping destination as needed. In an app with multiple activity destinations, each activity should have its own navigation graph.

- Transactions are removed. If you are navigating between fragment based screens under the same activity, then there is no longer a need for the FragmentManager. Fragment transactions are replaced by providing our navigation graph with actions, destinations and the navigating via the NavController.

###Abstract overview

- If we break the `Navigation Component` down to its most fundamental level then all we are left with is a container that handles the instantiation and navigation between fragments. So all we really need to do is to provide a container and hook up the wires.

###Diving in
- With all that being said we can now finally jump into some code. Now when creating a Navigation Component there are 5 basic steps that we should follow:
- **1)** Create a navigation graph
- **2)** Add a NavHost to the main Activity
- **3)** Add destinations to the navigation graph
- **4)** Connect the destinations
- **5)** Navigate with the NavController


###**1)** Create a navigation graph
- Now in order to create a navigation graph the first thing that we need to do is to create a resource folder. Right click on the res directory and select `new -> Android Resource File` You will then be presented with a new window. Inside of that new window, fill out the file name to what every you want, for us we went with `nav_graph`. You must ensure that the resource type is set to navigation and then click ok. If you look inside of the `res` folder you will notice that there is a new package called `navigation` and inside of that package is a new file called `nav_graph.xml`. This is the resource file that will get inflated to represent our navigation graph.


###**2)** Add a NavHost to the main Activity
- A quick reminder that NavHost acts as the container that will host all of the navigation interactions. So inside of our `main_activity.xml` we need to add a FragmentContainerView. If you  are unfamiliar with FragmentContainerView, it is simply a view that is specialized to hold fragments. So we go inside the `main_activity.xml` file and put this:

```
    <androidx.fragment.app.FragmentContainerView
        android:layout_width="match_parent"
        android:id="@+id/fragment_container_view"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"

        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph"/>
```
- Now this looks like a normal FragmentContainerView but look closely at the last 3 attributes: 

#####android:name="androidx.navigation.fragment.NavHostFragment"
- First lets talk about the `android:name` because this alone is a very important part of the FragmentContainerView. When we set the `android:name` we are telling the FragmentContainerView to do a one time transaction and this transaction consists of 3 things:

**1) :** creates a new instance of the fragment
**2) :** calls Fragment.onInflate() to inflate the Fragment
**3) :** Executes a fragment transaction to add the Fragment to the appropriate Fragment Manager

- So when we set the name attribute to "androidx.navigation.fragment.NavHostFragment" it will go through the 3 statements that are stated above.

#####app:defaultNavHost="true"
- This ensures that our NavHostFragment intercepts the system back button so we are still able to navigate the back stack.

#####app:navGraph="@navigation/nav_graph"
- This attribute points to the navigation graph associated with this navigation host. Setting this property inflates our `nav_graph` file and sets the graph property on the NavHostFragment.


###**3)** Add destinations to the navigation graph
- Now we need to navigate to the `nav_graph.xml` file and make sure you have selected the design tab. You will be presented with the navigation editor, this tool allows us to visually edit our navigation graph.
- To add a new destination, simply click the plus icon and we will be presented with a list of all the possible destinations. Which is really just all of our fragments. You can also choose to create your own destination but for us we simply chose an existing fragment.

- Once we added our destinations we need to determine which of our destination should be the `home` destination. Click on the desired fragment and then click the `home` icon.

###**4)** Connecting Destinations
- When we connect two destinations we do so through actions. We can easily create actions by using the Graph Editor that is provided to us via the Navigation Editor. The Graph Editor is the middle section of the Navigation Editor. So click on the home destination and drag an arrow to another desired destination.

###**5)** Navigate with the NavController
```
public class MainFragment extends Fragment implements View.OnClickListener{
    private NavController navController;
    
    public MainFragment(){
        super(R.layout.main_fragment);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState){
        super.onViewCreated(view,savedInstanceState);
        this.navController = Navigation.findNavController(view);

        view.findViewById(R.id.button1).setOnClickListener(this);
        view.findViewById(R.id.button2).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        this.navController.navigate(R.id.action_mainFragment_to_fragmentOne);;
    }

}
```
- Just a quick refresher, a NavController is responsible for managing app navigation within a NavHost. In order to use a NavController we first have to have one and we are doing with `Navigation.findNavController(view)`. The Navigation class provides us with utility methods for finding the NavController. `findNavController(view)` will locate the NavController associated with the provided view.
- Now that we have the NavController we can navigate to the desired fragment with `navigate()`. This method takes a resource id that represents an action inside of our navigation map. With that we are now done.


#Conclusion
- Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on [Twitter](https://twitter.com/TristAndroidDev).