navController: NavHostController = rememberNavController()
navController는 Navigation을 관리하는 데 사용되는 NavHostController이다.
NavHostController는 Jetpack Compose에서 사용되며, 탐색 그래프를 관리하고 탐색 명령을 처리한다. 이를 통해 앱 내에서 화면 간의 탐색을 쉽게 관리할 수 있다.
rememberNavController() 함수는 현재 컴포넌트의 생명주기 동안 NavHostController를 보존하는 데 사용되며 NavHostController를 생성하고 기억하여 필요한 곳에서 다시 사용할 수 있도록 한다.
✨ 요약하면, navController는 Navigation을 제어하기 위해 사용되며, rememberNavController()를 통해 초기화되어 현재 컴포넌트의 생명주기 동안 유지된다.
@Composable
fun NavigationEx(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController()
) {
/*
* NavHost는 Navigation의 호스트를 나타내며, 이 안에 각각의 화면에 해당하는 composable 함수들을 포함한다.
* NavHost는 navController와 함께 사용된다.
* 현재 "Home"과 "Office"라는 두 개의 화면을 가지고 있다.
*/
NavHost(navController, "Home", modifier = modifier) {
composable("Home") {
Column {
Text("Home")
Button(
onClick = {
navController.navigate("Office")
}
) {
Text(text = "Office로 이동")
}
}
}
composable("Office") {
Column {
Text(text = "Office")
Button(
onClick = {
navController.navigate("Home")
}
) {
Text(text = "Home 이동")
}
}
}
}
}
NavHost는 Jetpack Compose에서 사용되는 화면 간 탐색을 처리하는 데 사용되는 호스트이다.
앱 내에서 화면 전환을 담당하는 영역으로, 다양한 화면을 표시하고 사용자의 상호작용에 따라 그 사이를 탐색할 수 있도록 한다.
☝🏻 NavHost는 NavHostController와 함께 사용되어야 하며, NavHostController는 NavHost에 대한 탐색을 제어하는 역할을 한다.
navController.navigate() 함수는 NavHostController를 통해 화면 간 탐색을 수행하는 메서드이다.
이 함수를 호출하면 NavHostController는 지정된 목적지로 화면을 변경하고 해당 목적지에 대한 적절한 UI를 표시한다.
Ex) navController.navigate("Home") :Home
이라는 목적지로 이동하라는 명령을 NavHostController에 전달한다. NavHostController는 이 명령을 처리하고, 해당 목적지에 대한 화면을 표시한다.
popUpTo는 목적지로 이동할 때 현재 스택에 있는 다른 목적지들을 모두 제거하는 데 사용된다.
이를 통해 사용자가 이전에 방문한 여러 화면을 스택에서 제거하고, 목적지로의 새로운 경로를 설정할 수 있다.
@Composable
fun NavigationEx(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController()
) {
NavHost(navController, "Home", modifier = modifier) {
composable("Home") {
Column {
Text("Home")
Button(
onClick = {
navController.navigate("Office") {
popUpTo("Home")
}
}
) {
Text(text = "Office로 이동")
}
Button(
onClick = {
navController.navigate("Playground") {
popUpTo("Home")
}
}
) {
Text(text = "Playground 이동")
}
}
}
composable("Office") {
Column {
Text(text = "Office")
Button(
onClick = {
navController.navigate("Home") {
popUpTo("Home")
}
}
) {
Text(text = "Home 이동")
}
Button(
onClick = {
navController.navigate("Playground") {
popUpTo("Home")
}
}
) {
Text(text = "Playground 이동")
}
}
}
...
}
}
navController.navigate("Office") { popUpTo("Home") }
Office
로 이동하면서, 현재 스택에 있는 모든 목적지를 제거하고Home
목적지만 남기는 명령으로Home
화면 이외의 다른 화면을 건너뛰고Office
화면으로 이동할 수 있다.
popUpTo("Home") { inclusive = true }
popUpTo 함수의 옵션 중 하나로, 해당 목적지를 포함하여 이전의 모든 목적지를 제거하는 데 사용된다.
해당 코드의 경우,Home
이전의 모든 목적지들을 스택에서 제거하고,Home
목적지도 함께 제거한다.
@Composable
fun NavigationEx(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController()
) {
NavHost(navController, "Home", modifier = modifier) {
composable("Home") {
Column {
Text("Home")
Button(
onClick = {
navController.navigate("Office") {
popUpTo("Home") {
/*
Home -> Office -> Playground 순으로 이동할 때
Home에서 Office로 이동할 때 처음의 Home을 없애서 Office가 된다.
Office에서 Playground로 이동할 때는 스택에 Office 밖에 없으므로 popUpTo는 동작하지 않고 바로 Playground로 이동한다.
inclusive 예시
Home -> Login -> Mail
popUpTo("Login") { inclusive = true }
이동하는 순간에 Login을 찾아 같이 제거함으로써 스택에는 Home, Mail만 남아있다.
메일을 확인한 후에 백버튼을 누르면 Home으로 탈출이 가능하다.
*/
inclusive = true
}
}
}
) {
Text(text = "Office로 이동")
}
Button(
onClick = {
navController.navigate("Playground") {
popUpTo("Home") {
inclusive = true
}
}
}
) {
Text(text = "Playground 이동")
}
}
}
...
navController.navigate("Home") { launchSingleTop = true }
navigate() 함수의 옵션 중 하나로, 목적지로 이동할 때 해당 목적지가 이미 스택의 맨 위에 있으면 새로운 인스턴스를 생성하지 않고, 기존의 인스턴스를 재사용하여 새로운 목적지로 이동하는 데 사용된다.
해당 코드의 경우,Home
목적지로 이동할 때, 스택의 맨 위에 있는 목적지가 이미Home
인 경우에는 새로운 인스턴스를 생성하지 않고, 기존의Home
인스턴스를 재사용하여 화면을 업데이트한다.
@Composable
fun NavigationEx(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController()
) {
NavHost(navController, "Home", modifier = modifier) {
composable("Home") {
Column {
Text("Home")
Button(
onClick = {
navController.navigate("Office") {
popUpTo("Home") {
inclusive = true
}
}
}
) {
Text(text = "Office로 이동")
}
Button(
onClick = {
navController.navigate("Playground") {
popUpTo("Home") {
inclusive = true
}
}
}
) {
Text(text = "Playground 이동")
}
Button(
onClick = {
navController.navigate("Home") {
launchSingleTop = true
}
}
) {
Text(text = "Home 이동")
}
}
}
...
@Composable
fun NavigationEx(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController()
) {
NavHost(navController, "Home", modifier = modifier) {
composable("Home") {
Column {
Text("Home")
Button(
onClick = {
navController.navigate("Office") {
popUpTo("Home") {
inclusive = true
}
}
}
) {
Text(text = "Office로 이동")
}
Button(
onClick = {
navController.navigate("Playground") {
popUpTo("Home") {
inclusive = true
}
}
}
) {
Text(text = "Playground 이동")
}
Button(
onClick = {
navController.navigate("Argument/test") {
launchSingleTop = true
}
}
) {
Text(text = "test 아이디로 연결")
}
}
}
...
/*
* 동적으로 생성된 경로에 대한 화면을 정의한다.
* "Argument/{userId}"는 경로 패턴을 나타낸다.
* {userId}는 동적인 부분으로, 사용자 ID와 같은 값을 나타낸다.
* { backStackEntry -> ... } 람다 함수는 해당 경로에 대한 라우팅 정보를 받아와서 화면을 구성한다.
* val userId = backStackEntry.arguments?.getString("userId") 는 백스택엔트리에서 "userId"라는 키를 가진 인수를 가져와서 "userId" 변수에 할당한다.
* Text(text = "userId: $userId")는 가져온 userId 값을 사용하여 화면에 표시하는 텍스트를 생성한다.
*/
composable("Argument/{userId}") { backStackEntry ->
val userId = backStackEntry.arguments?.getString("userId")
Text(text = "userId: $userId")
}
}
}