Jetpack Compose Navigation 정리
Navigation 구성요소
Navigation은 크게 3가지 구성요소로 이뤄진다.
NavController: 대상(즉, 앱의 화면) 간 이동을 담당한다.
NavGraph: 이동할 컴포저블 대상을 매핑을 담당
NavHost: NavGraph의 현재 대상을 표시하는 컨테이너 역할을 하는 컴포저블
NavController
NavController는 Navigation 구성요소의 중심 API로, 스테이트풀(Stateful)이며 앱의 화면과 각 화면 상태를 구성하는 컴포저블의 백 스택을 추적한다. 컴포즈 환경에서 NavController는 rememberNavController()를 이용하여 가져올 수 있다.
val navController = rememberNavController()
rememberNavController()를 호출하여 NavContoller 인스턴스를 생성할 때 유의해야 할 점은 상태호이스팅에 유의해야 한다. 컴포저블 계층 구조에서 NavController를 만드는 위치는 이를 참조해야 하는 모든 컴포저블이 액세스할 수 있는 곳이어야 한다. 이러한 구조가 상태 호이스팅의 원칙을 준수하는 것이다.
NavGraph
NavGraph는 ID로 가져올 수 있는 NavDestination 노드의 집합이다. NavGraph는 '가상' 대상 역할을 합니다. NavGraph 자체는 백 스택에 나타나지 않지만 NavGraph로 이동하면 시작 대상이 백 스택에 추가된다. 새로운 NavGraph는 대상을 추가하고 시작 경로을 설정할 때까지 유효하지 않다. 대상을 추가하는 방법은 NavGraphBuilder.composable() 함수를 이용한다. 자세한 내용은 아래에서 설명한다.
NavHost
NavHost는 자체 포함된 탐색이 발생할 수 있도록 Compose 계층 구조에 제공한다. 지정된 NavGraphBuilder 내의 모든 컴포저블을 제공된 navController에서 탐색할 수 있다. 즉 각 NavController를 단일 NavHost 컴포저블과 연결해야 한다. NavHost는 내부적으로 구성 가능한 대상을 지정하는 NavGraph와 NavController를 연결한다. 이 연결을 통해 NavController는 이동한 컴포저블 대상을 파악하고 이동할 수 있게 된다
public fun NavHost(
navController: NavHostController,
startDestination: String,
modifier: Modifier = Modifier,
route: String? = null,
builder: NavGraphBuilder.() -> Unit
)
NavHost의 원형을 살펴보면, 위와 같다navController: NavHostController 클래스의 인스턴스이다. navigate() 메서드를 호출하여 다른 대상으로 이동하는 등의 방식으로 화면 간에 이동하는 데 이 객체를 사용할 수 있다.
startDestination: 앱에서 NavHost를 처음 표시할 때 기본적으로 표시되는 대상을 정의하는 문자열 경로이다.
builder: NavGraphBuilder로 그래프를 생성하기 위해 사용되는 빌더이다. 여기에 NavGraphBuilder의 composable() 함수를 이용하여 경로 대상을 정의 할 수 있다.
Compose Navigation 적용하기
의존성 추가
(https://developer.android.com/jetpack/androidx/releases/navigation#declaring_dependencies)
dependencies {
def nav_version = "2.5.3"
implementation "androidx.navigation:navigation-compose:$nav_version"
}
경로 추가
앱에서 경로를 추가해야 한다. 경로는 탐색의 기본 개념 중 하나이다. 경로는 Destination에 상응하는 문자열이다. 보통 enum 클래스를 사용하여 경로를 정의하는 편이다.
enum class TestScreen() {
First,
Second,
Third
}
NavController 추가
NavController는 위에서 설명했듯이 상태 호이스팅에 유의하여 rememberNavController() 를 이용하여 선언할 수 있다.
@Composable
fun TestApp(modifier: Modifier = Modifier){
val navController = rememberNavController()
...
}
NavHost 추가 및 경로 정의
NavHost를 추가하고 내부에 NavGraphBuilder.composable() 함수를 이용하여 경로를 정의한다. composable은 2개의 매개변수가 필요하다.
route: 경로 이름에 해당하는 문자열입니다. 모든 고유 문자열을 사용할 수 있습니다. CupcakeScreen enum의 상수 이름 속성을 사용합니다.
content: 여기에서 특정 경로에 표시할 컴포저블을 호출할 수 있습니다.
route는 위에서 정의한 경로 (enum class를 사용했었다.)를 이용하여 route 매개변수를 전달하고, content는 컴포저블 함수로 Screen 등 표시할 컨텐츠가 포함된다.
@Composable
fun TestApp(modifier: Modifier = Modifier){
val navController = rememberNavController()
...
NavHost(
navController = navController,
startDestination = TestScreen.First.name,
modifier = modifier.padding(innerPadding)
) {
composable(route = TestScreen.First.name) {
FirstScreen(
...
)
}
composable(route = TestScreen.Second.name) {
SecondScreen(
...
)
}
composable(route = TestScreen.Third.name) {
ThirdScreen(
...
)
}
}
}
NavHost 의 매개변수를 살펴보면, 위에서 생성한 navController를 전달한다. 그리고 처음 시작점인 startDestination으로 TestScreen.First.name을 이용해 첫 경로를 설정하여 준다.
경로 간 이동하기 (navigate())
경로 간 이동을 위해 navController의 navigate() 함수를 이용한다. 아래 코드를 보면, FirstScreen의 버튼 클릭 이벤트에서 SecondScreen으로 이동하는 코드이다.
@Composable
fun TestApp(modifier: Modifier = Modifier){
val navController = rememberNavController()
...
NavHost(
navController = navController,
startDestination = TestScreen.First.name,
modifier = modifier.padding(innerPadding)
) {
composable(route = TestScreen.First.name) {
FirstScreen(
...,
onNextButtonClicked = {
navController.navigate(TestScreen.Second.name)
}
)
}
composable(route = TestScreen.Second.name) {
SecondScreen(
...
)
}
}
}
참고
https://developer.android.com/jetpack/compose/navigation
댓글
댓글 쓰기