Mobile Development 27 min read

Comprehensive Guide to Android Navigation Component: Usage, Deep Links, Safe Args, and Source Code Analysis

This article provides an in‑depth tutorial on Android’s Navigation component, covering core concepts, XML graph setup, fragment transactions, parameter passing via Bundle and Safe Args, deep‑link integration, animation configuration, stack management, and a detailed source‑code analysis for developers.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Comprehensive Guide to Android Navigation Component: Usage, Deep Links, Safe Args, and Source Code Analysis

Navigation is a part of the Android Jetpack suite that offers a new framework for managing Fragments, supporting smooth transitions, deep links, and safe argument passing. It can also handle Activity navigation, making it possible to design modular applications where each feature module can be an Activity with Fragments.

The three core concepts are Navigation Graph (an XML file under res/navigation/ describing navigation relationships), NavHost (a container Fragment that displays destination Fragments), and NavController (the controller that manages navigation actions).

To set up a project, add the Navigation dependencies in build.gradle :

def nav_version = "2.3.0"
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"

Create a navigation graph XML (e.g., nav_graph.xml ) defining fragments and actions, then add a NavHostFragment to the activity layout:

<fragment
    android:id="@+id/fragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:navGraph="@navigation/nav_graph" />

Navigation between pages is performed via actions using NavController . Example using a button click:

mBtnGoDetail.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        NavController controller = Navigation.findNavController(view);
        controller.navigate(R.id.action_homeFragment_to_detailFragment);
    }
});

Parameters can be passed with a Bundle :

Bundle bundle = new Bundle();
bundle.putString("product_name", "Apple");
bundle.putFloat("price", 10.5f);
NavController controller = Navigation.findNavController(view);
controller.navigate(R.id.action_homeFragment_to_detailFragment, bundle);

For type‑safe arguments, enable Safe Args in the Gradle files and define arguments in the navigation XML. The generated DetailFragmentArgs and direction classes allow fluent argument setting and navigation:

Bundle bundle = new DetailFragmentArgs.Builder()
    .setProductName("Apple")
    .setPrice(10.5f)
    .build()
    .toBundle();
NavController controller = Navigation.findNavController(view);
controller.navigate(R.id.action_homeFragment_to_detailFragment, bundle);

// Or using generated directions
mBtnGoDetailBySafe.setOnClickListener(
    Navigation.createNavigateOnClickListener(
        HomeFragmentDirections.actionHomeFragmentToDetailFragment()
            .setProductName("Apple")
            .setPrice(10.5f)));

Shared ViewModel instances can be used across destinations to keep UI state (e.g., login status) synchronized:

userViewModel.getUserModel().observe(getViewLifecycleOwner(), new Observer
() {
    @Override
    public void onChanged(UserModel userModel) {
        if (userModel != null) {
            mUserName.setText(userModel.getUserName());
        } else {
            mUserName.setText("未登录");
        }
    }
});

Animations for fragment transitions are configured directly in the navigation XML using app:enterAnim , app:exitAnim , app:popEnterAnim , and app:popExitAnim .

Navigation stack management includes handling the system back button (via app:defaultNavHost="true" ), custom back actions with popBackStack() or navigateUp() , and using popUpTo and popUpToInclusive to control which destinations are removed from the stack.

Deep links can be created via PendingIntent or URL schemes. Example of a pending‑intent deep link:

private void createNotification() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "ChannelName", NotificationManager.IMPORTANCE_DEFAULT);
        channel.setDescription("description");
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_launcher_foreground)
        .setContentTitle("促销水果")
        .setContentText("香蕉")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(getPendingIntent())
        .setAutoCancel(true);
    NotificationManagerCompat.from(this).notify(100001, builder.build());
}

private PendingIntent getPendingIntent() {
    Bundle bundle = new Bundle();
    bundle.putString("productName", "香蕉");
    bundle.putFloat("price", 6.66f);
    return Navigation.findNavController(this, R.id.fragment)
        .createDeepLink()
        .setGraph(R.navigation.nav_graph)
        .setDestination(R.id.detailFragment)
        .setArguments(bundle)
        .createPendingIntent();
}

URL‑based deep links are added in the navigation XML with a deepLink element and declared in the manifest using <nav-graph android:value="@navigation/nav_graph"/> . The app can be launched via an ADB command such as:

adb shell am start -a android.intent.action.VIEW -d "http://www.mywebsite.com/detail?productName=香蕉&price=10"

The article also compares a traditional Fragment‑based navigation implementation with the Navigation component, showing that Navigation reduces boilerplate, handles back‑stack automatically, and integrates easily with BottomNavigationView.

Source‑code analysis reveals that NavHostFragment mainly creates a container and a NavController , while the heavy lifting—XML parsing, destination creation, and navigation execution—is performed by NavController and its Navigator implementations (e.g., FragmentNavigator ), following dependency inversion and open‑closed principles.

In summary, the Navigation component offers a clean, extensible framework for managing fragment and activity navigation in Android apps, supporting deep links, safe arguments, animations, and stack control, allowing developers to focus on business logic.

AndroidTutorialFragmentDeep LinkSafe ArgsNavigation Component
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.