Skip to content

Android Navigation Safe Args — Complete Guide

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Android Navigation Safe Args. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

The Problem

You pass an argument to a fragment but it arrives as a String when you expected an Int, or the argument is null on a cold start.

Wrong Approach ❌

// Manual bundle — no type safety
val bundle = Bundle()
bundle.putString("id", "123") // Wrong type!
bundle.putString("name", "Alice")
findNavController().navigate(R.id.action_to_details, bundle)

// In the destination
val id = arguments?.getString("id") // Parsed manually, error-prone

Output: ClassCastException or missing arguments.

Right Approach ✅

// Safe Args generates Directions automatically
// In nav_graph.xml:
<fragment android:id="@+id/detailsFragment">
    <argument
        android:name="itemId"
        android:defaultValue="-1"
        app:argType="integer" />
    <argument
        android:name="itemName"
        app:argType="string"
        app:nullable="true" />
</fragment>

// Navigating (compile-time safe)
findNavController().navigate(
    HomeFragmentDirections.actionHomeToDetails(
        itemId = 42,
        itemName = "My Item"
    )
)

// Receiving (generated Args class)
val args: DetailsFragmentArgs by navArgs()
val id = args.itemId // Int, not nullable
val name = args.itemName // String?, nullable

Output: Type-safe, compile-time validated arguments.

Prevention

  • Enable safeArgs in build.gradle: id 'androidx.navigation.safeargs.kotlin'.
  • Always use navArgs() delegate to read arguments.
  • Define defaultValue for optional arguments.
  • Use Parcelable type for complex objects.

Common Mistakes with navigation safe args

  1. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  2. Using head and tail instead of pattern matching, causing runtime errors on empty lists
  3. Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks

These mistakes appear frequently in real-world Android code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What plugin generates Safe Args?

androidx.navigation:navigation-safe-args-gradle-plugin for Java, navigation-safe-args-kotlin for Kotlin. Apply it in your project-level build.gradle.

### Can I pass a custom Parcelable via Safe Args?

Yes. Use app:argType="your.package.YourParcelableClass". The class must implement Parcelable. Safe Args generates the type converter automatically.

### What happens if I don't provide a required argument?

Safe Args generates a default value for optional args. Required args without a default cause a build error — you must pass them when navigating.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro