๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“ฑ| Android/๐Ÿš€ | Jetpack

[Android, Kotlin] compose navigation์—์„œ data class tpye ๋„˜๊ธฐ๊ธฐ

by immgga 2023. 8. 11.

compose์—์„œ navigation์„ ์‚ฌ์šฉํ•  ๋•Œ, ํ™”๋ฉด ์ „ํ™˜ ์‹œ ๋ณ€ํ™˜๋  ํ™”๋ฉด์— ๊ธฐ์กด์˜ ํ™”๋ฉด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿด ๋•Œ์—๋Š” Navcontroller.navigate()์—๋‹ค๊ฐ€ ๋„˜๊ธธ ๋ฐ์ดํ„ฐ๋ฅผ param์œผ๋กœ ๋„ฃ์€ ๋‹ค์Œ์— NavHost์—์„œ composable()๋กœ navigate logic์„ ์ž‘์„ฑํ•˜๋ฉด ๋์—ˆ๋‹ค.

 

navigation ์ค‘ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์— ๊ด€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ ์•„๋ž˜ ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•˜๋ฉด ์ข‹์„ ๋“ฏํ•˜๋‹ค.

https://rkdrkd-history.tistory.com/51

 

[Android, Kotlin] Compose UI ์ •๋ฆฌ(7)

์ด์ „ ํฌ์ŠคํŒ… https://rkdrkd-history.tistory.com/50 [Android, Kotlin] Compose UI ์ •๋ฆฌ(6) ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” compose ui๋กœ bottom navigation์„ ๋งŒ๋“œ๋Š” ์˜ˆ์ œ๋ฅผ ์ •๋ฆฌํ•ด ๋ณผ ๊ฒƒ์ด๋‹ค. ์ด์ „ ํฌ์ŠคํŒ… https://rkdrkd-history.tistory.com/46 [

rkdrkd-history.tistory.com

ํ•˜์ง€๋งŒ ์ง€๋‚œ ํฌ์ŠคํŒ…์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์€ ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•์ธ ๊ฒฝ์šฐ(string, int ๋“ฑ๋“ฑ...)์˜ argument๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋งŒ ์•Œ์•„๋ดค์—ˆ๋‹ค.

์ด๋ฒˆ์— ํ† ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋ฉด์„œ data class type์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ฒจ์„œ ๋‚˜์ค‘์—๋„ ๊นŒ๋จน์ง€ ์•Š๊ฒŒ ํฌ์ŠคํŒ…์„ ์ž‘์„ฑํ•ด ๋ณด์•˜๋‹ค.

 

์žก๋‹ด์€ ์—ฌ๊ธฐ๊นŒ์ง€ ํ•˜๊ณ  ๋ฐ”๋กœ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž


1. naivgate ์—ฐ๊ฒฐํ•˜๊ธฐ

์ผ๋‹จ ๋จผ์ € ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ screen๊ณผ ๋ฐ›์„ screen ๊ฐ„์˜ navigation์„ ์—ฐ๊ฒฐํ•ด ์ค˜์•ผ ํ•œ๋‹ค.

๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ screen์„ ๋งŒ๋“ค์–ด ๋ณด์ž

@Composable
fun ProfileScreen(
	navigateToMain: () -> Unit
) {
	. . .
}

๋‚˜์ค‘์— profileScreen์˜ parameter์— ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ฌ ์˜ˆ์ •์ด๋‹ค.

 

๊ทธ๋‹ค์Œ profileScreen์˜ route๋ฅผ ์ƒ์„ฑํ•˜๊ณ , navigate ๋กœ์ง์„ ์ƒ์„ฑํ•œ๋‹ค.

const val profileRoute = "profile"

fun NavController.navigateToProfile() {
    this.navigate(profileRoute)
}

 

๋‹ค์Œ์œผ๋กœ NavHost์— profileScreen์„ ์ถ”๊ฐ€ํ•ด ์ฃผ๋ฉด profileScreen์—์„œ ํ•  ์ž‘์—…์€ ๋๋‚œ๋‹ค.

fun NavGraphBuilder.profileScreen(
    navigateToMain: () -> Unit
) {
    composable(profileRoute) {
        ProfileScreen(navigateToMain = navigateToMain)
    }
}

 

navigateToMain์€ main๊ณผ profile screen ๊ฐ„์˜ ํ™”๋ฉด ์ „ํ™˜์„ ์œ„ํ•ด ์ถ”๊ฐ€ํ•ด ๋†“์•˜๋‹ค.

 

์ด์ œ mainScreen์—์„œ ํ•ด์•ผ ํ•  ์ž‘์—…์œผ๋กœ ๋„˜์–ด๊ฐ€ ๋ณด์ž.

profileScreen์—์„œ ์ž‘์—…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋˜‘๊ฐ™์ด ํ•ด์ฃผ๋ฉด ์„œ๋กœ navigate ํ•˜๋Š” ํ™”๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

์ฝ”๋“œ๋ฅผ ๋บ€ ๊ฒƒ์€ ์ ˆ๋Œ€ ๊ท€์ฐฎ์•„์„œ๊ฐ€ ์•„๋‹ˆ๋‹ค!

 

2. ๋ฐ์ดํ„ฐ ๋„˜๊ธฐ๋Š” ๋กœ์ง ์ƒ์„ฑํ•˜๊ธฐ

main screen์— navigateProfile param์„ ์ƒ์„ฑํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ด ์ฃผ๊ณ  card์˜ onclick์— navigateToProfile์— ์—ฐ๊ฒฐํ•ด ์ค€๋‹ค.

๋ฐ์ดํ„ฐ ์ƒ์„ฑ์€ ์ž„์‹œ๋กœ ๋งŒ๋“ค์–ด๋„, api๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  response ๊ฐ’์œผ๋กœ ํ•ด์ค˜๋„ ์ƒ๊ด€์—†๋‹ค. ๋ฌผ๋ก  card๋„ ๊ผญ card๊ฐ€ ์•„๋‹ˆ์–ด๋„ ๋œ๋‹ค!!(clickable ํ•œ ๋ชจ๋“  compos function์—์„œ ๊ฐ€๋Šฅํ•˜๋‹ค.)

@Composable
fun MainScreen(
	navigateToProfile: (teamData: UserDomain, userData: UserDataDomain) -> Unit
) {
	// set send data
	Card(onClick = navigateToProfile(teamData, userData)) {
    
    }
}

 

๋‹ค์Œ์œผ๋กœ ์ด์ „์— ์ƒ์„ฑํ•œ navigateToProfile๋กœ ์ด๋™ํ•ด mainscreen์—์„œ ์ถ”๊ฐ€ํ•œ navigateToProfile()๋กœ ์ด๋™ํ•ด parameter๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  route๋ฅผ ์ˆ˜์ •ํ•ด ์ฃผ๋„๋ก ํ•˜๊ฒ ๋‹ค.

route๋Š” ๋ฐ›์€ paramter๋“ค ๋ชจ๋‘ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด dataClass.data ์ด๋Ÿฐ ํ˜•์‹์œผ๋กœ ๋„ฃ์œผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋‹ˆ๊นŒ ์ฐธ๊ณ ํ•˜๋„๋ก ํ•˜์ž.

fun NavController.navigateToProfile(teamDataJson: String, userDataJson: String) {
    this.navigate("$profileRoute/$teamDataJson/$userDataJson")
}

์œ„์˜ ์ฝ”๋“œ์—์„œ ์ด์ƒํ•œ ์ ์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค.

๋ฐ”๋กœ navigateToProfile์ด string์ด๋ผ๋Š” ์ ์ธ๋ฐ ๋‹ค์Œ ์ฝ”๋“œ์—์„œ ์™œ ๊ทธ๋Ÿฐ์ง€ ์ด์œ ๋ฅผ ์•Œ๋ ค์ฃผ๊ฒ ๋‹ค.

 

NavHost์— mainScreen์„ ์ถ”๊ฐ€ํ•œ ๋ถ€๋ถ„์œผ๋กœ ์ด๋™ํ•œ๋‹ค.

NavHost(
    navController = navHostController,
    startDestination = BottomNavItem.Main.route
) {
    mainScreen(
        navigateToProfile = { teamData, userData ->
            val teamJson = Uri.encode(Gson().toJson(teamData))
            val userJson = Uri.encode(Gson().toJson(userData))
            navHostController.navigateToProfile(teamJson, userJson)
        }
    )
}

์ด์ œ์•ผ ๋งํ•˜๋Š” ๊ฑฐ์ง€๋งŒ ํ•„์ž๋Š” ์ „๋‹ฌํ•  data class๋ฅผ json string์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์ „๋‹ฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ๋•Œ, json string์„ data class๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค.

๊ทธ๋ž˜์„œ navigateToProfile์—์„œ string์„ param์œผ๋กœ ๋ฐ›์€ ๊ฒƒ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ตณ์ด json string์œผ๋กœ ๋ฐ”๊พผ ์ด์œ ๋Š” ํ•„์ž๋Š” data class ์ค‘ url์„ ๋ฐ›๋Š” data๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ ์œ—๊ธ€์—์„œ ๋งํ•œ ๊ฒƒ์ฒ˜๋Ÿผ route๋ฅผ ๋ฐ”๊ฟ€ ๋•Œ, ๋ฐ›์€ param ํ†ต์งธ๋กœ ๋„ฃ์–ด์ค˜์•ผ ํ•˜๋Š”๋ฐ url์€ route๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์—์„œ encoading ๊ด€๋ จ์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์—ˆ๋‹ค.(๊ทธ ์˜ค๋ฅ˜ ๋•Œ๋ฌธ์— 4์‹œ๊ฐ„์„ ๋‚ ๋ ธ๋‹ค ใ… ) ๊ทธ๋ž˜์„œ json string์œผ๋กœ ํ•˜๋Š” ์•„์ด๋””์–ด๋ฅผ ์ƒ๊ฐํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. string์€ ๋ณ€ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค!

 

์„ค๋ช…์ด ๊ธธ์—ˆ๋‹ค. ๋‹ค์‹œ ์ฝ”๋“œ๋กœ ๋Œ์•„๊ฐ€์ž

์ „๋‹ฌ๋ฐ›์€ data๋ฅผ ์จ๋จน๊ธฐ ์œ„ํ•ด navHost์— ์ถ”๊ฐ€ํ•œ profileScreen์œผ๋กœ ์ด๋™ํ•˜์ž.

fun NavGraphBuilder.profileScreen(navigateToStella: () -> Unit) {
    composable(
        route = "$profileRoute/{teamData}/{userData}",
        arguments = listOf(
            navArgument("teamData") { type = NavType.StringType },
            navArgument("userData") { type = NavType.StringType }
        )
    ) { navBackStackEntry ->
        val teamDataJson = navBackStackEntry.arguments?.getString("teamData")
        val teamData = Gson().fromJson(teamDataJson, UserDomain::class.java)

        val userDataJson = navBackStackEntry.arguments?.getString("userData")
        val userData = Gson().fromJson(userDataJson, UserDataDomain::class.java)

        ProfileScreen(
            teamData = teamData,
            userData = userData,
            navigateToStella = navigateToStella
        )
    }
}

route์—๋Š” navigateToProfile์—์„œ ์ˆ˜์ •ํ–ˆ๋˜ route ํ˜•์‹์„ ๊ทธ๋ž˜๋„ ์จ์ค€๋‹ค.

arguments์—๋Š” route์— ์ง€์ •ํ•œ name์„ list๋กœ ๋ฐ›์•„ stringType๋กœ ์ ์šฉํ•ด ์ค€๋‹ค.

๊ทธ ์ดํ›„ composable์˜ navBackStackEntry๋ฅผ ์ด์šฉํ•ด ์ง€์ •ํ•œ name๋“ค์„ ๋ถˆ๋Ÿฌ์™€ ๋‹ค์‹œ data class type์œผ๋กœ ๋ณ€ํ™˜ํ•ด ์ฃผ์—ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  profileScreen์— param์œผ๋กœ ๋„ฃ์–ด ์ฃผ๋ฉด ์ž‘์—… ์™„๋ฃŒ์ด๋‹ค.

 

 

์ •๋ฆฌ


์˜ˆ์ „์— ์ž ๊น ๋ฐฐ์›Œ๋ณธ ์ง€์‹์„ ๊ฒ€์ƒ‰ํ•˜๋ฉด์„œ ๋‹ค์‹œ ๊ณต๋ถ€ํ•ด ๋ณด์•˜๋Š”๋ฐ, ์˜ˆ์ „ ๊ธฐ์–ต์ด ์ƒ๊ธฐ๋˜์–ด์„œ ๊ณต๋ถ€ํ•˜๊ธฐ ํŽธํ–ˆ์—ˆ๋‹ค.

์˜ค๋ฅ˜ ๋‚˜๊ธฐ ์ „์— ์ด ์ƒ๊ฐ์„ ๋จผ์ € ํ–ˆ์œผ๋ฉด ํ•˜๋Š” ํ›„ํšŒ๋„ ๋“ค์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

๊ทœ๋ชจ๊ฐ€ ํฐ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” data class๋ฅผ ๋„˜๊ฒจ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ํ—ˆ๋‹คํ•  ๊ฒƒ ๊ฐ™์€๋ฐ ๊ทธ ์‚ฌ๋žŒ๋“ค์—์„œ ์ด ํฌ์ŠคํŒ…์ด ๋„์›€์ด ๋˜์—ˆ์œผ๋ฉด ์ข‹๊ฒ ๋‹ค.

 

์งˆ๋ฌธ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ๊ฐ€ ์ž˜๋ชป๋˜์—ˆ๊ฑฐ๋‚˜ ๋” ํšจ์œจ์ด ์ข‹์€ ์ฝ”๋“œ๋ฅผ ์•Œ๊ณ  ๊ณ„์‹  ๋ถ„๋“ค์€ ๋Œ“๊ธ€ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

728x90