Navigation is a concept of Navigation, that is, Activity and fragment are regarded as Destination destinations one by one, and each Destination forms a Navigation graph called NavGraph, and the Navigation controller NavController uniformly schedules jumps. This article starts with a brief look at the sample code that comes with AS.

Jetpack note code

This article source code is based on SDK 29, IDE is Android Studio 3.5.3

use

Create projects, introduce dependencies,

implementation 'androidx. Navigation: navigation - fragments: 2.2.2'
implementation 'androidx. Navigation: navigation - UI: 2.2.2'
Copy the code

And then new Activity, bottom Navigation Activity, IDE will create 3 fragments and viewModel, 1 activity and layout file, 1 menu file bottom_nav_menu, 1 navigation file mobile_navigation, run as follows:


Let’s look at the layout file,

<androidx.constraintlayout.widget.ConstraintLayout>
    <! -- Navigation View at the bottom, menu file defines 3 items -->
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        app:menu="@menu/bottom_nav_menu" />

    <! Fragment as a page container, navGraph specifies the structure of navigation graph -->
    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost="true"
        app:navGraph="@navigation/mobile_navigation" />

</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code

Go to your mobile_navigation,

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mobile_navigation"
    app:startDestination="@+id/navigation_home">

    <fragment
        android:id="@+id/navigation_home"
        android:name="com.holiday.jetpackstudy.navigation.ui.home.HomeFragment"
        tools:layout="@layout/fragment_home" />

    <fragment
        android:id="@+id/navigation_dashboard"
        android:name="com.holiday.jetpackstudy.navigation.ui.dashboard.DashboardFragment"
        tools:layout="@layout/fragment_dashboard" />

    <fragment
        android:id="@+id/navigation_notifications"
        android:name="com.holiday.jetpackstudy.navigation.ui.notifications.NotificationsFragment"
        tools:layout="@layout/fragment_notifications" />
</navigation>
Copy the code

StartDestination specifies the starting point of the navigation diagram (HomeFragment). Switch AS to the Design view.


This allows you to visually manage your navigation chart structure and then look at your activities,

public class NavigationActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_navigation);
        BottomNavigationView navView = findViewById(R.id.nav_view);
        // Build the configuration class with three destination Fragments
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications)
                .build();
        // Build navigation controllers with fragments
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        // Set the configuration class for the navigation controller
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        // Associate NavigationView with navigation controller
        NavigationUI.setupWithNavController(navView, navController);
    }

}
Copy the code

That’s about it. Let’s look at the internal implementation.

The principle of

AppBarConfiguration. Builder to the destination (the destination all pages) are stored by the

//AppBarConfiguration.java
 Builder(int. topLevelDestinationIds) {for (intdestinationId : topLevelDestinationIds) { mTopLevelDestinations.add(destinationId); }}Copy the code

NavigationUI setupActionBarWithNavController is simple set parameters,

//NavigationUI.java
void setupActionBarWithNavController(AppCompatActivity activity,NavController navController, AppBarConfiguration configuration) {
    navController.addOnDestinationChangedListener(
        new ActionBarOnDestinationChangedListener(activity, configuration));
}
Copy the code

Then NavigationUI. SetupWithNavController associated NavigationView and navigation controller,

//NavigationUI.java
void setupWithNavController(final BottomNavigationView bottomNavigationView,
            final NavController navController) {
    // Set the click event for the bottom navigation
    bottomNavigationView.setOnNavigationItemSelectedListener(
        new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                // Bottom navigation toggle button
                returnonNavDestinationSelected(item, navController); }});// Update the selected status of the bottom navigation without looking at it
    navController.addOnDestinationChangedListener(xxx)
}

boolean onNavDestinationSelected(MenuItem item,NavController navController) {
    / / navigation
    navController.navigate(item.getItemId(), null, options);
}
Copy the code

Come to NavController,

//NavController.java
// omit the call chain to come
void navigate(NavDestination node, Bundle args, NavOptions navOptions, Navigator.Extras navigatorExtras) {
    NavDestination newDest = navigator.navigate(node, finalArgs,
                navOptions, navigatorExtras);
}
Copy the code

Navigate to navigator. Navigate to find multiple implementation classes,


Here we’re using FragmentNavigator,

//FragmentNavigator.java
NavDestination navigate(Destination destination, Bundle args, NavOptions navOptions, Navigator.Extras navigatorExtras) {
    // Get the fragment class name
    String className = destination.getClassName();
    // reflection creates a fragment
    Fragment frag = instantiateFragment(mContext, mFragmentManager,
                className, args);
    // Familiar fragment transaction
    FragmentTransaction ft = mFragmentManager.beginTransaction();
    // Display the fragment as replace
    ft.replace(mContainerId, frag);
    // Commit the transaction
    ft.commit();
}
Copy the code

Each time the destination is changed, the fragment is repeatedly destroyed and rebuilt. It is developed according to the idea of only one activity per APP recommended by Google, which is ok. However, the fragment here is used as three permanent pages on the home page, and we hope to save it. Destruction and reconstruction require re-request of network data and re-initialization of view, which seriously affects user experience. The author will discuss the fragment reuse scheme in the next article.

Refer to the article

  • Navigation: a very awkward Fragment management framework

This article is formatted using MDNICE