오늘은 각각 다른 origin(출발지)에서 공유되는 Screen 으로 route가 들어오는 경우,
그것의 처리 방법에 대해서 정리해 보도록 하겠습니다.
1. 큰 그림
각각 다른 Origin에서 들어오는 경우의 생각해야 할 문제점은,
다른 UI에서 각각 다른 데이터를 들고 들어온다는 것 입니다.
이것은 origin 별로 다르게 데이터를 처리해서 보여주어야 한다는 것을 의미합니다.
이 문제를 해결하기 위한 방법은 여러가지이겠지만,
다음과 같은 방법이 있을 수 있겠네요.
우선은 isFromXXOrigin 이라는 boolean 을 route의 argument 로 받아서,
그것을 보고 각기 다르게 처리하는 방식이구요.
다른 하나는 Sealed Class를 사용해서 route를 구분해서 받는 것 입니다.
- isFromXXOrigin argument 값을 받아서 보고 처리
- NavigationEvent Sealed Class를 만들어서 route들을 선언해서 사용
- 어떤 Event에서 온 것인지 라우트를 보고 처리
첫 번째 방법이 구현하기 훨씬 쉽다고 할 수 있구요.
Sealed Class를 사용하는 방법은 좀 더 유연하고 확장성 있다고 할 수 있습니다.
나중에 공유되는 페이지로 들어오는 origin이 늘어나더라도 쉽게 대응할 수 있으니까요.
이 글에서는 두 번째 Sealed Class를 사용하는 방법에 대해서 정리해 보도록 하겠습니다.
2. SealedClass 로 다른 Route 정의하기
먼저 할일은 각각의 다른 Origin에서 나오는 route 를 정의하는 것 입니다.
여기서는 아래와 같이 2가지의 NavigationEvent를 정의하였습니다.
route에 data를 전달할 때, 사용할 util함수로 generate Route라는 함수를 포함시켰습니다.
values()는 NavEvent 를 묶어서 반복문으로 한번에 전달하기 위해서,
companion object에 추가해 주었습니다.
generateRoute의 인자로 Map타입을 사용한 이유는,
이 글에서는 데이터를 1개만 넘기고 있지만,
나중에 인자로 데이터들을 전달할 때,
여러개의 데이터를 넘기는 경우도 있을 수 있으니 그렇게 하였습니다.
sealed class NavEvent {
abstract val route: String
abstract val arguments: List<NamedNavArgument>
object FromFirstPage : NavEvent() {
override val route: String = "third_page/from_first_page/{data}"
override val arguments: List<NamedNavArgument>
}
object FromSecondPage : NavEvent() {
override val route: String = "third_page/from_second_page/{id}"
override val arguments: List<NamedNavArgument>
}
fun generateRoutes(argumentsMap: Map<String, Any>): String {
var resultRoute = route
argumentsMap.forEach { (key, value) ->
resultRoute = resultRoute.replace("{$key}", value.toString())
}
return resultRoute
}
companion object {
fun values() = listOf(FromFirstPage, FromSecondPage)
}
}
3. Navigation 정의
이제 Navigation의 컨테이너인 NavHost에 Navigation을 정의해서 사용해 보겠습니다.
위에서 Companion Object 에 정의했던, values()함수를 이용해서,
반복문으로 navEvent들을 가져옵니다.
val navController = rememberNavController()
NavHost(navController, startDestination = "first_page") {
composable("first_page") {
FirstPage(navController)
}
composable("second_page") {
SecondPage(navController)
}
NavEvent.values().forEach { navEvent ->
composable(
route = navEvent.route,
arguments = navEvent.navArguments
) { backStackEntry ->
val id = backStackEntry.arguments?.getInt("id")
ThirdPage(navEvent)
}
}
}
이렇게 해서 각각 다른 origin 으로부터 공유되는 Page에 대해서 처리를 할 수 있게 되었습니다.
3. Composable 정의
위의 Event 를 사용할 각각의 페이지들을 정의해 줍니다.
간단하게 Button을 누르면, 값을 넘겨주고 실행되도록 하였습니다.
@Composable
fun FirstPage(navController: NavController) {
Column {
Text("여기는 First Page")
Button(onClick = {
navController.navigate(
NavEvent.FromFirstPage.generateRoutes(mapOf("id" to 1))
)
}) {
Text("Second Page로 이동")
}
}
}
@Composable
fun SecondPage(navController: NavController) {
Column {
Text("여기는 Second Page")
Button(onClick = {
navController.navigate(
NavEvent.FromSecondPage.generateRoutes(mapOf("id" to 2)))
Text("Third Page로 이동")
}
}
}
그럼 이제 first와 second에서 도착하게 될, thirdPage 만 만들어주면 되겠습니다.
각각의 페이지별로 다른 데이터를 받은 것을 볼 수 있습니다.
@Composable
fun ThirdPage(navEvent: NavEvent) {
when (navEvent) {
is NavEvent.FromFirstPage -> {
//여기서는 String 타입의 data를 받음
val data = navEvent.data
}
is NavEvent.FromSecondPage -> {
// 여기서는 Int 타입의 id 값을 받음
val id = navEvent.id
}
}
Column {
Text("Third Page")
Text("들어오는 페이지별로 다른 데이터를 받았음")
}
}
위에서는 ThirdPage에서 NavEvent를 받아서 구분하여 처리하였지만,
arguments에 route를 추가해서,
viewModel에서 route를 보고 처리할 수 있도록 해도 될 것 같습니다.
참고로 ViewModel에서 argument를 받는 방법은 아래 글을 참조해 주세요.
>> Route 에서 전달된 값을 ViewModel 에서 받는 방법 # Jetpack Compose Navigaion savedStateHandle
'Android Jetpack Compose > Navigation, Route' 카테고리의 다른 글
Bottom Navigation 구현방법 총정리 # Route (0) | 2023.05.29 |
---|---|
Navigation 구현 방법 총정리 # Route Jetpack Compose (0) | 2023.05.27 |
Nested Navigation 구현 및 총정리 # 중첩 Route Jetpack Compose (0) | 2023.05.26 |
공유되는 Route 의 Navigation 구현방법 # Jetpack Compose (0) | 2023.04.22 |
Route 에서 전달된 값을 ViewModel 에서 받는 방법 # Jetpack Compose Navigaion savedStateHandle (0) | 2023.04.13 |
Navigation Drawer 구현방법 # Jetpack Compose (0) | 2022.11.16 |
Navigation 과 Bottom Navigation 구현방법 정리 # Jetpack Compose (1) | 2022.10.19 |
댓글