์ฌ์ฐจ์ ์ฐจ ํ๋ค๋ณด๋ ํ๋ก์ ํธ ์ฝ๋์ ๋ค๋น๊ฒ์ด์ ๋ถ๋ถ์ ๋ ๋ ค๋ฒ๋ ธ๋ค๐ฅฒ
๋ค์ํ๋ ค๊ณ ํ๋๋ฐ ์ฝ๋๋ฅผ ์์ด๋ฒ๋ ค์ ๋์ค์ ๋ ์ด๋ด๊น๋ด ๋ฏธ๋ฆฌ ๊ณต์ ๋ฌธ์๋ฅผ ์ข ์ ๋ฆฌํ๋ค.
์ฌ์ค ๊ท์ฐฎ์ ์์ ์ผ ์ค ์์๋๋ฐ ๊ทธ๋์ ์๋ก ์ ๋ฐ์ดํธ๋ ๋ถ๋ถ์ ์ ํด๋ณด๊ฒ ๋์ด์ ๋๋ฆ ๋ณด๋์์๋ค.
compose navigation์ ์ ํ์ํ๊ฐ?
์ฌ์ค ์ฒ์์๋ ์ปดํฌ์ฆ์ ์ด๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ตณ์ด ์ฌ์ฉํ ํ์๊ฐ ์์๊น ์๊ฐ์ด ๋ค์๋ค.
์กฐ๊ฑด๋ฌธ์ผ๋ก UI๋ฅผ ์ ์ดํ๋ฉด ํ๋ฉด ์ ํ์ ๊ตฌํํ ์ ์์๊ฑฐ๋ผ๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ ์ง๋ง ํ๋ฉด์ ์ ์ดํ๋ค๋ ๊ฒ์ ํ๋ฉด์ ์ด๋ ๋ฟ๋ง ์๋๋ผ ๊ทธ ์ด๋ ๊ฐ ๋ฐ์ดํฐ ์ ๋ฌ, ๋ฐฑ์คํ ๊ด๋ฆฌ ๋ฑ ์๊ฐ๋ณด๋ค ๊ณ ๋ คํด์ผํ ์ฌํญ์ด ๋ง์๊ณ , compose navigation๋ฅผ ํตํด ์ด๋ฌํ ๋ถ๋ถ์ ๊ฐํธํ๊ฒ ์ฌ์ฉํ ์ ์๋ค๋ ์ ์ด ์ฅ์ ์ด๋ผ๊ณ ์๊ฐํ๋ค.
์ฉ์ด
Controller
: destination๊ฐ ์ด๋์ ์ ์ดํ๋ central coordinator.Host
: ํ์ฌ ํ๋ฉด์ ํฌํจํ๋ UI์์, ๋์ถฉ ์ก์ ๊ฐ์๊ฑฐ๋ผ๊ณ ์๊ฐํ๋ฉด ํธํจ. ๋ด๋ถ์ ํ๋ฉด์ ์์๋ฐ๊ฟ์ ์ํ๋ destination์ ๋ณด์ฌ์ค ์ ์๋ ํ๋ฉด ์ก์๊ฐ์ ๋๋.Graph
: ์ฑ ๋ด์ ๋ชจ๋ navigation destination๊ณผ ํ๋ฉด ์ฐ๊ฒฐ ๋ฐฉ์์ ์ ์ํ๋ ์๋ฃ๊ตฌ์กฐ. ์ฌ๊ธฐ์ ๋ฏธ๋ฆฌ ์ ์๋ ํ๋ฉด์ผ๋ก๋ง ์ด๋ํ ์ ์๋ค. ๋์ถฉ ์ง๋ ๋๋.Destination
: navigation graph์ ๋ ธ๋. host๊ฐ ๋ณด์ฌ์ฃผ๋ ํ๋ฉดRoute
: destination์ผ๋ก ์ด๋ํ๋๋ฐ ์ฌ์ฉ๋๋ ๊ฒฝ๋ก. destination๊ณผ ์ด๋ ์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๊ณ ์ ํ๊ฒ ์๋ณํ๊ธฐ ์ํ Serializable๊ฐ์ฒด(ex ๋ฌธ์์ด)
๊ฐ์ธ์ ์ผ๋ก๋ ๊ฐ๋ ์์ฒด๋ ์ฝ๊ฐ ์ด๋ฐ ๋๋์ด๋ค.
dependency
compose navigation์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ๋ชจ๋ ๋ ๋ฒจ์ build.gradle ํ์ผ์ ์๋์ ๊ฐ์ ์์กด์ฑ์ ์ถ๊ฐํด ์ฃผ์ด์ผํ๋ค.
2.8.0-alpha08
์ด ๋ฒ์ ์ ๋ถ๊ธฐ๋ก ํ์
์์ ์ฑ์ ๊ฐ์ง route์ ๋ํ ์
๋ฐ์ดํธ๊ฐ ์์๋ค.
ํ์ ์์ ์ฑ์ ์ํ route ์ ๋ฐ์ดํธ๋ฅผ ์ ์ฉํ๋ ค๋ฉด ํด๋น ๋ฒ์ ์ด์์ผ๋ก ๋ฒ์ ์ ์ค์ ํด์ผํ๋ค.
dependencies{
val nav_version="2.8.0-alpha08"
implementation ("androidx.navigation:navigation-compose:$nav_version")
}
๊ฐ๋จํ ์ฌ์ฉ๋ฒ
1. navigation Controller์์ฑ
val navController=rememverNavController()
- ์ปดํฌ์ ๋ธ ๊ณ์ธต๊ตฌ์กฐ์์ ์ฐธ์กฐํ ๋ชจ๋ ์ปดํฌ์ ๋ธ์ ์ฐธ์กฐ ํ ์ ์๋ ๊ณ์ธต์์ ์์ฑํด์ผํ๋ค. (state hoisting)
2. navigation Host์์ฑ
๋ฐฉ๋ฒ1) route๋ฅผ ํ์ ์ผ๋ก ์ ๋ฌํ๊ธฐ (*Navigation 2.8.0-alpha08ย ์ด์์์๋ง ๊ฐ๋ฅ)
- ๋งค๊ฐ๋ณ์ ๋ณด๋ด๋๋ฐ ํ์ ์์ ์ฑ์ ๋ํ ์ ์๋ ๋ฐฉ๋ฒ์ด๋ค.
//@Serializable์ด๋
ธํ
์ด์
์ฌ์ฉ์ ์ํ ์์กด์ฑ ์ถ๊ฐ
//build.gradle(module)
plugins {
kotlin("plugin.serialization") version "2.0.0" // ์ฌ์ฉ์ค์ธ ์ฝํ๋ฆฐ ๋ฒ์ ์ ๋ง์ถฐ์ผ ์ค๋ฅ๊ฐ ์๋๋๊ฒ ๊ฐ๋ค.
}
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1")
}
@Serializable
object Profile
@Serializable
object FriendsList
NavHost(navController=navController,startDestination=ScreenA){
//์๊ธฐ๊ฐ NavGraphBuilder์์ญ์ผ๋ก, ์ฌ๊ธฐ ์ฝ๋๋ก NavGraph๊ฐ ์ ์๋์ด NavHost์๊ฒ ์ ๋ฌ๋๋ค.
composable<ScreenA>{ScreenA(/*...*/)}
composable<ScreenB>{ScreenB(/*...*/)}
}
๋ฐฉ๋ฒ2) route์ string์ด๋ id์ ๋ฌ
- NavHost์์ NavGraph๋ฅผ ๋ง๋ค๋ route์ string์ด๋ ์ ์ id๋ฅผ ์ ๋ฌํ ์ ์๋ค.
๐จย ์ด ๊ฒฝ์ฐ ๋์ค์ ๋งค๊ฐ๋ณ์๋ฅผ ๋ณด๋ผ ๋ โscreenA/arg1/arg2โ ๋ญ ์ด๋ฐ ์์ผ๋ก route๋ฅผ ์ ๋ฌํ๊ฒ ๋์ Type safetyํ์ง ์๋ค.
NavHost(navController=navController,startDestination="ScreenA"){
//๊ฐ์ธ์ ์ผ๋ก ์ด๋ถ๋ถ์ ๋ค๋ฅธ ํ์ผ์ด๋ ํ์ฌ๊ฐ ๋ฐ๋ก ๊ด๋ฆฌํด๋ ์ข์๊ฒ๊ฐ๋ค.
composable(route="ScreenA"){ScreenA(/*...*/)}
composable(route="ScreenB"){ScreenB(/*...*/)}
}
graph:NavGraphBuilder.()->Unit={
composable(route="ScreenA"){ScreenA(/*...*/)}
composable(route="ScreenB"){ScreenB(/*...*/)}
}
NavHost(navController=navController,startDestination=ScreenA,builder=graph)
//ํ๋ฉด์ด ๋ง์ผ๋ฉด graph๋ถ๋ถ์ ๋ค๋ฅธ ํ์ผ๋ก ๋นผ๋๊ฒ ๋์์ง ๋ ์ ์์ง ์์๊น?
โก๏ธ NavHost
@Composable
public fun NavHost(
navController: NavHostController,
startDestination: String,
modifier: Modifier = Modifier,
contentAlignment: Alignment = Alignment.Center,
route: String? = null,
enterTransition: (AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition) =
{ fadeIn(animationSpec = tween(700)) },
exitTransition: (AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition) =
{ fadeOut(animationSpec = tween(700)) },
popEnterTransition: (AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition) =
enterTransition,
popExitTransition: (AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition) =
exitTransition,
builder: NavGraphBuilder.() -> Unit
)
โก๏ธ NavGraph
public fun NavGraphBuilder.composable(
route: String,
arguments: List<NamedNavArgument> = emptyList(),
deepLinks: List<NavDeepLink> = emptyList(),
enterTransition: (@JvmSuppressWildcards
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? = null,
exitTransition: (@JvmSuppressWildcards
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? = null,
popEnterTransition: (@JvmSuppressWildcards
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? =
enterTransition,
popExitTransition: (@JvmSuppressWildcards
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? =
exitTransition,
content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit
)
3. destination์ผ๋ก ์ด๋
navController๋ฅผ ํ์ฉํ์ฌ destination์ผ๋ก ์ด๋ํ ์ ์๋ค.
๋ค์ํ๊ฒ overload ๋์ด ์์ด ์ํฉ์ ๋ง์ถฐ ์ฌ์ฉํ๋ฉด ๋๋ค.
@MainThread
public void navigate(@NonNull Uri deepLink)
@MainThread
open fun navigate(resId: @IdRes Int): Unit
@MainThread
open fun navigate(directions: NavDirections): Unit
//.. ๋ฑ๋ฑ
- Composable๋ก ์ด๋ ์
@Serializable
object FriendsList
navController.navigate(route = FriendsList)
//or route๋ฅผ string์ผ๋ก ์ฌ์ฉ์
navController.navigate("FriendsList")
๐จย ์ฃผ์ํ ์ ์ ๋ง์ฝ ์ปดํฌ์ ๋ธ ๋ด๋ถ์์ ํ๋ฉด์ด๋์ ์ ์ดํ๊ณ ์ถ์ ์ ์์ ์ปดํฌ์ ๋ธ๋ก navController๋ฅผ ๋ณด๋ด์ ์์ ์ปดํฌ์ ๋ธ ๋ด๋ถ์์ navigate๋ฅผ ํธ์ถํ๋ฉด ์๋๋ค. UDF(๋จ๋ฐฉํฅ ๋ฐ์ดํฐํ๋ก์ฐ)์์น์ ๋ฐ๋ผ ์ด๋ฒคํธ๋ฅผ ๋ ธ์ถํด์ ์์์์ NavController๋ฅผ ์ ์ดํด์ผํ๋ค.
@Composable
fun Parent(){
val navController=rememberNavController()
//...
Child(){
navController.navigate(/*destination route*/)
}
}
@Composable
fun Child(onScreenChange:()->Unit){
}
์ฐธ๊ณ
Navigation with Compose ย |ย Jetpack Compose ย |ย Android Developers
Navigation ย |ย Android Developers
Kotlinx-Serialization | ๋งค์ฌ์ ์๋๋ก์ด๋ ๊ฐ๋ฐ์
GitHub - Kotlin/kotlinx.serialization: Kotlin multiplatform / multi-format serialization
๋๊ธ๋จ๊ธฐ๊ธฐ