
In this article, we’ll learn how to pass data between screens in Jetpack Compose.
Prerequisites:
We’ll make the following app in this article:

There are two screens – WelcomeScreen and DetailsScreen. In the WelcomeScreen, we enter the name and age. We display their values in the DetailsScreen.
Let’s make the app.
First, create an empty Compose project and add the following dependency in the app-level gradle file.
// navigation
implementation "androidx.navigation:navigation-compose:2.7.2"
Next, open MainActivity and add the following code:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.compose.rememberNavController
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
YourProjectNameTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
AppUI()
}
}
}
}
}
@Composable
fun AppUI() {
}
Create the following Kotlin files in your project:
- WelcomeScreen.kt
- DetailsScreen.kt
- NavGraph.kt
- Screen.kt (sealed class)

We added 2 screens: WelcomeScreen, DetailsScreen. They represent the corresponding screens (destinations).
The Screen is a sealed class. It is used to store the list of all the screens.
In the NavGraph, we add the navigation graph.
Let’s write the code in each file.
WelcomeScreen.kt:
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Button
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
@Composable
fun WelcomeScreen(navController: NavHostController) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Welcome Screen"
)
Spacer(modifier = Modifier.height(height = 8.dp))
// name text field
var name by remember {
mutableStateOf("")
}
OutlinedTextField(
value = name,
onValueChange = { newValue ->
name = newValue
},
label = { Text(text = "Name") },
placeholder = { Text(text = "Enter your name") }
)
Spacer(modifier = Modifier.height(height = 8.dp))
// age text field
var age by remember {
mutableStateOf("")
}
OutlinedTextField(
value = age,
onValueChange = { newValue ->
age = newValue
},
label = { Text(text = "Age") },
placeholder = { Text(text = "Enter your age") },
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number
)
)
Spacer(modifier = Modifier.height(height = 8.dp))
// submit button
Button(
onClick = {
navController.navigate(route = Screen.Details.route)
}
) {
Text(text = "Submit")
}
}
}
We added two text fields and a button. When we click on the button, we’ll navigate to the DetailsScreen. Currently, we are not passing the data.
DetailsScreen.kt:
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@Composable
fun DetailsScreen(name: String?, age: String?) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Details Screen")
Text(text = "Name: $name")
Text(text = "Age: $age")
}
}
It displays the name and age that we receive from the HomeScreen.
Screen.kt:
sealed class Screen(val route: String) {
object Welcome: Screen(route = "welcome_screen")
object Details: Screen(route = "details_screen")
}
It contains the screens.
NavGraph.kt:
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
@Composable
fun SetupNavGraph(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = Screen.Welcome.route
) {
composable(
route = Screen.Welcome.route
) {
WelcomeScreen(navController)
}
composable(
route = Screen.Details.route
) {
// pass an empty string for now
// we'll send the original data
DetailsScreen(name = "", age = "")
}
}
}
We set up the NavHost with our two screens.
Next, open MainActivity and add the following code in the AppUI().
@Composable
fun AppUI() {
val navController = rememberNavController()
SetupNavGraph(navController = navController)
}
Now, run the project. If you click on the submit button, you should navigate to DetailsScreen.

Let’s pass the data. First, we need to add the arguments to the route parameter. Open Screen.kt and change the Details object.
sealed class Screen(val route: String) {
object Welcome: Screen(route = "welcome_screen")
object Details: Screen(route = "details_screen" + "/{name_key}" + "/{age_key}")
}
We add arguments in the following format:
route = "screen_name" + "/{key1}" + "/{key2}" + "/{key3}"
The key1, key2, and key3 are used to identify the arguments. In our example, we added name_key for the name and age_key for the age.
Next, we pass the data to a screen in the navigation graph. Open NavGraph.kt and change the code related to DetailsScreen.
@Composable
fun SetupNavGraph(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = Screen.Welcome.route
) {
composable(
route = Screen.Welcome.route
) {
WelcomeScreen(navController)
}
composable(
route = Screen.Details.route,
arguments = listOf(
navArgument(name = "name_key") {
type = NavType.StringType
},
navArgument(name = "age_key") {
type = NavType.StringType
}
)
) { navBackStackEntry ->
val name = navBackStackEntry.arguments?.getString("name_key")
val age = navBackStackEntry.arguments?.getString("age_key")
DetailsScreen(name = name, age = age)
}
}
}
The arguments parameter of composable() accepts a list of arguments. We create the arguments using the navArgument() method. You need to specify the corresponding key and the data type of the argument.
To extract these values, use the navBackStackEntry parameter, which is available in the lambda of the composable() function.
val name = navBackStackEntry.arguments?.getString("name_key")
val age = navBackStackEntry.arguments?.getString("age_key")
For other data types, use the corresponding methods. For example, use the getInt() method for integers.
val someInteger = navBackStackEntry.arguments?.getInt("key")
Next, open WelcomeScreen.kt and pass the values in the buttons onClick block.
// submit button
Button(
onClick = {
navController.navigate(route = "details_screen" + "/$name" + "/$age")
}
) {
Text(text = "Submit")
}
To pass the data from one screen to another, we use the route parameter of the navigate() function:
navController.navigate(route = "screen_name" + "/data1" + "/data2" + "/data3")
Here, the arguments data1, data2, and data3 are assigned to the corresponding keys. In our example, name and age are assigned to the name_key and age_key respectively.
Now, run the app. Enter the name and age in the HomeScreen. You will see their values in the DetailsScreen.

Our app works as expected, but we can improve our code. We hardcoded details_screen and key values. Let’s change them.
In the Screen.kt, modify the Details object.
const val NAME_KEY = "name_key"
const val AGE_KEY = "age_key"
sealed class Screen(val route: String) {
object Welcome: Screen(route = "welcome_screen")
object Details: Screen(route = "details_screen" + "/{$NAME_KEY}" + "/{$AGE_KEY}") {
fun getFullRoute(name: String, age: String): String {
return "details_screen" + "/$name" + "/$age"
}
}
}
We added two constant values and a method. The method takes the data and returns the full route as a string. We call it from the HomeScreen.
// submit button
Button(
onClick = {
navController.navigate(route = Screen.Details.getFullRoute(name = name, age = age))
}
) {
Text(text = "Submit")
}
Next, in the navigation graph, replace the hardcoded keys with their variable names.
@Composable
fun SetupNavGraph(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = Screen.Welcome.route
) {
composable(
route = Screen.Welcome.route
) {
WelcomeScreen(navController)
}
composable(
route = Screen.Details.route,
arguments = listOf(
navArgument(name = NAME_KEY) {
type = NavType.StringType
},
navArgument(name = AGE_KEY) {
type = NavType.StringType
}
)
) { navBackStackEntry ->
val name = navBackStackEntry.arguments?.getString(NAME_KEY)
val age = navBackStackEntry.arguments?.getString(AGE_KEY)
DetailsScreen(name = name, age = age)
}
}
}
This is how we pass data between screens in Jetpack Compose. I hope you have learned something new. If you have any doubts, leave a comment below.
Related Articles:
References: