#1 ์ด์ ๊ธ
[Android] Jetpack Compose - Navigation ๊ธฐ์ด
#1 ๊ฐ์#1-1 ์ ํต์ ์ธ ์๋๋ก์ด๋ ํ๋ก์ ํธ์์์ Navigation [Android] Navigation - ๊ธฐ์ด#1 ์ด์ ๊ธ [Android] Navigation - ํ๊ฒฝ ์ค์ #1 Navigation#1-1 ์กํฐ๋นํฐ ๋ฐ ํ๋๊ทธ๋จผํธ ๊ตฌ์ฑ์ ํธ๋ ๋์์ฆ ์๋๋ก์ด๋ ๊ฐ๋ฐ
kenel.tistory.com
๋ณธ ๊ฒ์๊ธ์์ ์ ๊ฒ์๊ธ์ ์์ฑ๋ ์ฑ์ ์ผ๋ถ ์์ ํ์ฌ, Destination๋ผ๋ฆฌ ์๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๊ฒ ๋ง๋ค์ด๋ณธ๋ค.
์ด๋ฅผ ์ํด์ ๋จผ์ NavBackStackEntry์ ๋ํด ์์์ผ ํ๋ค. ์ด๋ฆ์์ ๋ณด๋ฏ, NavBackStackEntry์ ๋ฐฑ ์คํ์ ๊ด๋ฆฌํ๋ ๊ฐ์ฒด๋ค. ๋ฐ๋ผ์, Back Stack(๋ฐฑ ์คํ)์ด ๋ญ์ง ์์์ผ NavBackStackEntry๋ฅผ ์ดํดํ ์ ์๋ค.
#2 Back Stack
#2-1 ์ผ๋ฐ์ ์ธ ๊ฐ๋
๋ฐฑ ์คํ์ ๋ง์น ์น ๋ธ๋ผ์ฐ์ ์์์ ๋ฐฉ๋ฌธ ๊ธฐ๋ก๊ณผ ๊ฐ๋ค๊ณ ํ ์ ์๋ค. ์น ์ํ์ ํ๋ค๊ฐ ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ๊ฐ์ฅ ์ต๊ทผ์ ๋ฐฉ๋ฌธํ ํ์ด์ง๋ถํฐ ๊ฐ์ฅ ์์ ์ ๋ฐฉ๋ฌธํ๋ ํ์ด์ง ์์ผ๋ก ์ด๋ํ๋ ๊ฒ๊ณผ ๊ฐ์ด, ์๋๋ก์ด๋ ์ฑ ๊ตฌ์กฐ์์๋ ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ๊ฐ์ฅ ์ต๊ทผ์ '๋ฐฉ๋ฌธ'ํ ํ๋ฉด์์ ๊ฐ์ฅ ์์ ์ ๋ฐฉ๋ฌธํ๋ ํ์ด์ง๋ก ์ด๋ํ๋ค (๊ณ์ ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ค๋ณด๋ฉด ๋ ์ด์ ๋ฐฉ๋ฌธํ๋ ํ๋ฉด์ด ๋จ์์์ง ์๊ฒ๋ ํ
๋ฐ, ์ฌ๊ธฐ์ ํ๋ฒ ๋ ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ์ฑ์ด ์ข
๋ฃ๋๋ค).
#2-2 ์๋๋ก์ด๋ ํ๋ก์ ํธ์์์ ๊ฐ๋

์ด์ ๊ฒ์๊ธ(#1)์ ์์ฑ๋ ์ฑ์์ "Go to Second Screen"๊ณผ "Go to First Screen" ๋ฒํผ์ ๋ณด์ด๋ ๋๋ก ๊ณ์ ๋๋ฅด๋ฉด ์์ ๊ฐ์ ๋ฐฑ ์คํ์ด ํ์ฑ๋๋ค. ๋งจ โ์ชฝ์ ์๋ ํ๋ฉด์์ ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ์ค๋๋ ์ชฝ(โ)์ผ๋ก ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ค. ์ฌ๊ธฐ์ ์ง์ด์ผํ ์ ์ด ์๋ค. ๋ฐ๋ก "๋ฐฑ ์คํ์๋ Back์ด๋ผ๋ ๋จ์ด๊ฐ ํฌํจ๋์ด ์์ผ๋, 'ํ์ฌ ๋ณด์ด๋ ํ๋ฉด'์ Back Stack์ ํฌํจ๋์ง ์๋๊ฑด๊ฐ?"๋ผ๋ ์๋ฌธ์ด ๊ทธ๊ฒ์ด๋ค. ์๋๋ค, ์ ์ด๋ ์๋๋ก์ด๋ ํ๋ก์ ํธ์์์ Back Stack ๊ฐ๋
์์ 'ํ์ฌ ๋ณด์ด๋ ํ๋ฉด' ๋ํ Back Stack์ ํฌํจ๋๋ค. ์ฆ, ์ ๋์๋์์ ๋งจ โ์ชฝ์ ์๋ ํ๋ฉด ๋ํ ๋ฐฑ์คํ์ ํฌํจ๋ ์ํ๋ผ๋ ๊ฒ์ด๋ค.
#3 NavBackStackEntry - ๋ฐ์ดํฐ ์ ๋ฌ
#3-1 ๊ฐ๋
์๋๋ก์ด๋ Navigation ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋์ผ๋ก ์์ฑํ์ฌ ๊ด๋ฆฌํ๋ Destination์ Back Stack ํ๋ํ๋์ ๊ตฌ์ฑ ํญ๋ชฉ(Entry)์ ๋งํ๋ค. ๊ฐ Destination์ ์์ํ๋ ๋ฉํ ๋ฐ์ดํฐ๋ผ๊ณ ๋ ํ ์ ์๋ค. ์ด ๊ฐ์ฒด๋ Navigation ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋จ์์ ์์์ ๋ง๋ค๊ณ ๊ด๋ฆฌํด์ค๋ค. ๋ฐ๋ผ์ #2-2์ ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ ์ํฉ์์ NavBackStackEntry๋ ์ด 6๊ฐ๊ฐ ์์์ ์ผ๋ก ๋ง๋ค์ด์ ธ ํด๋น ๋ฐฑ์คํ์ ์์๊ฐ ์ ๊ฑฐ๋ ๋๊น์ง ๊ฐ์ด ์ด์ ์์ ๊ฒ์ด๋ค.
#3-2 Destination์ content
// in MyNavHost.kt
composable(
route = "secondScreen",
) { backStackEntry ->
// backStackEntry๋ฅผ ๊ฐ์ง๊ณ ๋ฌด์ธ๊ฐ ํ๋ ์ฝ๋
}
์ด์ ๊ฒ์๊ธ์ #2-4์์ ๋ณด๋ฏ, Destination์ content ์ธ์๋ ๊ทธ ๋ฐ์ดํฐํ์ด @Composable (NavBackStackEntry) -> Unit์ด๋ค. ๋ค๋ฅธ ์ผ๋ฐ์ ์ธ ์ปดํฌ์ ๋ธ ํจ์๋ค์ content ์ธ์ ํ์
์ด @Composable () -> Unit์ธ ๊ฒ๊ณผ ๋ฌ๋ฆฌ ๋ง์ด๋ค. ์ด๋ ์ ์ฝ๋์ ๊ฐ์ด Destination์ ํ์ ์ปดํฌ์ ๋ธ(content)๊ฐ NavBackStackEntry๋ฅผ ์ฐธ์กฐํ ์ ์๋ค๋ ๋ง์ด ๋๋ค.
#2-2์์ Back Stack์ ํ์ฌ Destination๋ ํฌํจํ๋ ๊ฐ๋
์ด๋ผ๊ณ ํ๋ค. ๋ฐ๋ผ์ ์ ์ฝ๋์ backStackEntry๋ ํ์ฌ Destination์๊ฒ ์ ๋ฌ๋ ์ ๋ณด๋ผ๋ ๊ฒ์ ์์ง ๋ง์. "Back์ด๋ผ๋ ๋จ์ด๊ฐ ์์ผ๋ ์ด์ (Back) Destination์ ๋ํ ์ ๋ณด์ธ๊ฐ?" ๋ผ๊ณ ๋ฌด์ฌ์ฝ ์๊ฐํด์๋ ์ ๋๋ค.
#3-3 NavBackStackEntry.arguments ๊ตฌ์กฐ ์ ์
NavBackStackEntry์ arguments ํ๋กํผํฐ๋ ๋ฐฑ ์คํ์ ๊ฐ ์์๋ง๋ค ๊ฐ๋ณ์ ์ผ๋ก ์ ์ฅ๋๋ ๋ฐ์ดํฐ๋ค. #3-2์ Destination ์ฝ๋๊ฐ arguments๋ฅผ ๊ฐ์ง๊ฒ ๋ง๋ค์ด ๋ณด๊ฒ ๋ค. ์๋ฅผ ๋ค์ด String ํ์
๋ฐ์ดํฐ ํ๋์ Int ํ์
๋ฐ์ดํฐ ํ๋์ฉ์ arguments์ ์ ์ํ๋ค๋ฉด, ์๋์ ๊ฐ์ ๋ชจ์์ด ๋๋ค.
// in MyNavHost.kt
composable(
// (2) route ์์
route = "secondScreen/{sampleStringDataName}/{sampleIntDataName}",
// (1) arguments ์ถ๊ฐ
arguments = listOf(
navArgument("sampleStringDataName") {
type = NavType.StringType
},
navArgument("sampleIntDataName") {
type = NavType.IntType
}
)
) { backStackEntry ->
// backStackEntry๋ฅผ ๊ฐ์ง๊ณ ๋ฌด์ธ๊ฐ ํ๋ ์ฝ๋
}
(1) arguments ์ถ๊ฐ
์ฌ๊ธฐ์, "์ ๊ตณ์ด type์ NavType์ด๋ผ๋ ๋ณ๋์ ์ธ์คํด์ค๊น์ง ์ด์ฉํด์ ๋ช
์ํ๋๊ฐ?"๋ผ๋ ์๋ฌธ์ด ๋ค ์ ์๋๋ฐ, Destination ๊ฐ ๋ฐ์ดํฐ๋ String ํ์
์ผ๋ก๋ง ์ ๋ฌ๋๊ธฐ์, ์์ ํ ํ์
์บ์คํ
์ ๋ณด์ฅํด ๋ฐํ์ ์๋ฌ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํจ์ด๋ผ๊ณ ํ๋ค. ํ์
์ ๋ช
์ํจ์ผ๋ก์จ, ํต์ ๊ฐ ์ด๋ ค์ด ๋ฐํ์ ์๋ฌ๋ฅผ ํต์ ๊ฐ๋ฅํ ์ปดํ์ผ ์๋ฌ๋ก ๋์ฒดํ ์ ์๋ ๊ฒ์ด๋ค.
(2) route ์์
arguments ์ธ์๋ฅผ ์ถ๊ฐํ ๊ฒ ๋ฟ๋ง ์๋๋ผ route ์ธ์์ ๋ฌธ์์ด๋ ์ ์ฝ๋์ ๊ฐ์ ํ์์ผ๋ก ๋ณ๊ฒฝํ๋ค. ์๋ํ๋ฉด, ๋ฐ์ดํฐ๋ฅผ route ๋ฌธ์์ด ์์ ๋ด์ ๋ณด๋ด๊ธฐ ๋๋ฌธ์ด๋ค (#3-4 ์ฐธ์กฐ). route ์์ฒด์ ์ ๋ณด๋ฅผ ์ค์ด ๋ณด๋ธ๋ค๋ ์ ์ด, ๋ง์น ์น ํ๋ก๊ทธ๋๋ฐ์์ URL์ ๋ฐ์ดํฐ๋ฅผ ์ค์ด ๋ณด๋ด๋ GET ์์ฒญ๊ณผ ๋น์ทํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ ์ฝ๋๋ arguments ํ๋กํผํฐ์ ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ด์ ๊ฒ์ด ์๋๋ผ, arguments๋ฅผ ์ฃผ๊ณ ๋ฐ๊ธฐ ์ํ ๊ตฌ์กฐ๋ฅผ ์ ์ํ ๊ฒ์ ๋ถ๊ณผํ๋ค. ์ค์ ๋ก Destination์ arguments์ ๋ฐ์ดํฐ๋ฅผ ๋ด์ผ๋ ค๋ฉด ์ถ๊ฐ ์์
์ด ํ์ํ๋ค.
#3-4 NavBackStackEntry์ ๋ฐ์ดํฐ(arguments) ๋ด์ ๋ณด๋ด๊ธฐ
composable(
route = "firstScreen", arguments = listOf()
) {
FirstScreen(navigateToSecondScreen = { navController.navigate("secondScreen/HelloWorld/123") })
}
#3-3์์ Second Screen Destination์ route ์ธ์ ๋ฌธ์์ด ํ์์ ์๋กญ๊ฒ ์์ฑํ์๋ค. NavHostController.navigate()์ ์ ๋ฌํ ๋ฌธ์์ด ํ์๋ ์ด์ ๋ง์ถ๋ค. ์ฌ๊ธฐ๊น์งํด์ผ ๋น๋ก์ arguments์ ๋ฐ์ดํฐ๊ฐ ๋ด๊ธด๋ค.
#3-5 NavBackStackEntry์์ ๋ฐ์ดํฐ(arguments) ๊ฐ์ ธ์ค๊ธฐ
// in MyNavHost.kt
composable(
route = "secondScreen/{sampleStringDataName}/{sampleIntDataName}",
arguments = listOf(
navArgument("sampleStringDataName") {
type = NavType.StringType
},
navArgument("sampleIntDataName") {
type = NavType.IntType
}
)
) { backStackEntry ->
SecondScreen(navigateToFirstScreen = { navController.navigate("firstScreen") })
Log.i("interfacer_han", "${backStackEntry.arguments?.getString("sampleStringDataName")}")
Log.i("interfacer_han", "${backStackEntry.arguments?.getInt("sampleIntDataName")}")
}
NavBackStackEntry.arguments๋ฅผ ์ฐธ์กฐํด ๋ฐ์ดํฐ๋ฅผ ๋ฝ์๋ธ๋ค. ๋๋ Log ๋ฉ์์ง๋ง ์ฐ๊ณ ๋๋์ง๋ง, ์ ์ฝ๋์ ์๋ SecondScreen๊ณผ ๊ฐ์ ์ปดํฌ์ ๋ธ ํจ์์ ์์ฑ์์ ์ ๋ฌํ๋ ์์ผ๋ก๋ ์์ฉ์ด ๊ฐ๋ฅํ ๊ฒ์ด๋ค.
#3-6 ์๋ ํ์ธ (๋ก๊ทธ ๋ฉ์์ง)
HelloWorld
123
#3-5๊น์ง์ ์ฝ๋๋ฅผ ์คํ์์ผ๋ณด๋ฉด ๋์ค๋ ๋ก๊ทธ ๋ฉ์์ง๋ค.
#4 ์์ฝ
NavBackStackEntry๋ ๋ฐฑ ์คํ์ ํ ์์๋ค. NavBackStackEntry๊ฐ ์ํํ๋ ๋ฐ์ดํฐ ์ ๋ฌ์ ํ์์ ์น ํ๋ก๊ทธ๋๋ฐ์์์ GET ์์ฒญ๊ณผ ๋น์ทํ๋ค.
#5 ์์ฑ๋ ์ฑ
android-practice/jetpack-compose/ArgumentsOfNavBackStackEntry at master ยท Kanmanemone/android-practice
Contribute to Kanmanemone/android-practice development by creating an account on GitHub.
github.com
'๊นจ์ ๊ฐ๋ ๐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] Pointer input - AwaitPointerEventScope()์ ๋ฉ์๋๋ค (0) | 2025.02.08 |
---|---|
[Android] Pointer input - PointerInputChange, PointerEvent (0) | 2025.02.07 |
[Android] Jetpack Compose - Navigation ๊ธฐ์ด (0) | 2024.09.12 |
[Android] Jetpack Compose - ๊ฐ์ฒด ์งํฅ์ UI ๋ ์ด์ด ์ค๊ณ (0) | 2024.09.11 |
[Android] Jetpack Compose - Side-effects (0) | 2024.09.06 |