Challenge 2: Pass an Argument with SafeArgs — Solution
// app/build.gradle.kts (or the project-level build.gradle.kts, depending
// on Gradle version) — add the SafeArgs plugin
plugins {
id("androidx.navigation.safeargs.kotlin")
}
// res/navigation/nav_graph.xml — declare the argument on detailsFragment
// WelcomeFragment.kt — sending, via the generated Directions class
binding.viewDetailsButton.setOnClickListener {
val action = WelcomeFragmentDirections.actionWelcomeToDetails(message = "Hello from Welcome!")
findNavController().navigate(action)
}
// DetailsFragment.kt — receiving, via the generated Args class
class DetailsFragment : Fragment() {
private lateinit var binding: FragmentDetailsBinding
private val args: DetailsFragmentArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
binding = FragmentDetailsBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.detailText.text = args.message
}
}
Notes:
- WelcomeFragmentDirections.actionWelcomeToDetails(...) and
DetailsFragmentArgs are BOTH generated automatically by the SafeArgs
plugin from the nav graph's declaration — neither class is
hand-written.
- The parameter name (message) is checked by the compiler at the call
site — passing the wrong type, or forgetting a required argument
entirely, is a compile error, not a runtime crash the way a mistyped
Intent extra key would be (Chapter 4).
- val args: DetailsFragmentArgs by navArgs() uses Kotlin's property
delegation (Kotlin Intermediate Chapter 4) — navArgs() is itself a
delegate that reads the Fragment's arguments Bundle and exposes it as
a typed args object.