Navigation

AAC Jetpack Navigation Component

Android Architecture Component Library 쀑 ν•˜λ‚˜μΈ Navigation 에 λŒ€ν•΄μ„œ λ„μ Ήμ–΄λ΄…λ‹ˆλ‹€πŸ§

Jetpack 쀑 ν•˜λ‚˜μΈ Navigation Component λŠ” μ•‘ν‹°λΉ„ν‹°λ‚˜ ν”„λž˜κ·Έλ¨ΌνŠΈ κ°„μ˜ 이동을 μ•ˆμ •μ μ΄κ³  κ°„λ‹¨ν•˜κ²Œ λ„μ™€μ£ΌλŠ” μ»΄ν¬λ„ŒνŠΈμ΄λ‹€. λ˜ν•œ ν™”λ©΄κ°„μ˜ 이동을 iOS 의 storyboard 처럼 직관화할 수 μžˆμ–΄ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 화면흐름을 μ‰½κ²Œ μ•Œ 수 μžˆλ‹€. Android Document에 λͺ…μ‹œλœ λ„€λΉ„κ²Œμ΄μ…˜ λ„μž…μœΌλ‘œ μΈν•œ μž₯점은 μ•„λž˜μ™€ κ°™λ‹€.

  • ν”„λž˜κ·Έλ¨ΌνŠΈ νŠΈλžœμž­μ…˜ 처리

  • ν™”λ©΄κ°„μ˜ 이동을 μ˜¬λ°”λ₯΄κ²Œ 처리

  • μ• λ‹ˆλ©”μ΄μ…˜κ³Ό 전에 λŒ€ν•œ ν‘œμ€€ν™”λœ λ¦¬μ†ŒμŠ€ 제곡

  • λ”₯ 링크 κ΅¬ν˜„ 및 처리 용이

  • μ΅œμ†Œν•œμ˜ μΆ”κ°€μž‘μ—…μœΌλ‘œ 상단 νˆ΄λ°”/ ν•˜λ‹¨ λ„€λΉ„κ²Œμ΄μ…˜μ„ 포함

  • Safe Args - ν™”λ©΄ μ „ν™˜κ°„μ˜ 데이터 전달을 전달할 λ•Œ μ•ˆμ •μ„±μ„ 제곡

  • ViewModel 지원

κ΅¬μ„±μš”μ†Œ

λͺ¨λ“  λ„€λΉ„κ²Œμ΄μ…˜ κ΄€λ ¨ 정보가 ν•˜λ‚˜μ˜ λͺ¨μ—¬μžˆλŠ” XML λ¦¬μ†ŒμŠ€μ΄λ‹€. μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ λ‚΄ ν™”λ©΄κ°„μ˜ 이동에 λŒ€ν•΄ ν”Œλ‘œμš°λ₯Ό μ§κ΄€ν™”ν•˜μ—¬ ν•œ λˆˆμ— μ•Œμ•„λ³΄κΈ° μ‰½κ²Œ 확인할 수 μžˆλ‹€.

Navigation Graphμ—μ„œ λŒ€μƒμ„ ν‘œμ‹œν•˜λŠ” 빈 μ»¨ν…Œμ΄λ„ˆμ΄λ‹€. κ΅¬μ„±μš”μ†Œμ—λŠ” ν”„λž˜κ·Έλ¨ΌνŠΈ λŒ€μƒμ„ ν‘œμ‹œν•˜λŠ” κΈ°λ³Έ NavHost κ΅¬ν˜„μΈ NavHostFragment κ°€ ν¬ν•¨λœλ‹€.

NavHost μ—μ„œ μ•± 탐색을 κ΄€λ¦¬ν•˜λŠ” 객체이닀. NavController λŠ” μ‚¬μš©μžκ°€ μ•± λ‚΄μ—μ„œ 이동할 λ•Œ NavHost μ—μ„œ λŒ€μƒ ν™”λ©΄μ˜ μ „ν™˜μ„ μ‘°μ’…ν•œλ‹€

κ΅¬ν˜„

- Navigation 라이브러리 μΆ”κ°€ (build.gradle)

def nav_version = "2.5.0"

implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

- Navigation Graph μΆ”κ°€

  1. res λ””λ ‰ν† λ¦¬μ—μ„œ New > Android Resource File 을 μ„ νƒν•œλ‹€.

  2. 파일λͺ… μž…λ ₯ (ex: nav_graph)

  3. ResourceType 섀정을 Navigation 으둜 μ„ νƒν•œλ‹€.

- NavHost μΆ”κ°€ (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_container"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>

앑티비티에 ν”„λž˜κ·Έλ¨ΌνŠΈλ“€μ˜ μ»¨ν…Œμ΄λ„ˆ 역할을 ν•˜λŠ” NavHost κ΅¬ν˜„μΈ NavHostFragment λ₯Ό μΆ”κ°€ν•œλ‹€.

android:name 속성은 NavHost κ΅¬ν˜„μ˜ 클래슀 이름을 ν¬ν•¨ν•œλ‹€.

app:navGraph 속성은 NavHostFragment λ₯Ό Navigation Graph(탐색 κ·Έλž˜ν”„) 와 μ—°κ²°ν•œλ‹€. 탐색 κ·Έλž˜ν”„λŠ” μ‚¬μš©μžκ°€ 이동할 수 μžˆλŠ” 이 NavHostFragment 의 λͺ¨λ“  λŒ€μƒμ„ μ§€μ •ν•œλ‹€

app:defaultNavHost 속성을 true둜 μ„€μ •ν•˜λ©΄ NavHostFragment κ°€ μ‹œμŠ€ν…œ λ’€λ‘œκ°€κΈ° λ²„νŠΌμ„ κ°€λ‘œμ±•λ‹ˆλ‹€. λ™μΌν•œ λ ˆμ΄μ•„μ›ƒμ— μ—¬λŸ¬ ν˜ΈμŠ€νŠΈκ°€ μžˆλ‹€λ©΄(예: 창이 2개인 λ ˆμ΄μ•„μ›ƒ) ν•œ 호슀트만 κΈ°λ³Έ NavHost둜 지정해야 ν•œλ‹€. - Navigation Graph λŒ€μƒ μΆ”κ°€ 이제 λ„€λΉ„κ²Œμ΄μ…˜μ—μ„œ μ‚¬μš©ν•  ν”„λž˜κ·Έλ¨ΌνŠΈλ“€μ„ nav_graph.xml 에 μΆ”κ°€ν•œλ‹€.

nav_graph.xml νŒŒμΌμ„ μ—΄κ³  μ•„λž˜μ™€ 사진에 ν‘œμ‹œλœ λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ ν”„λž˜κ·Έλ¨ΌνŠΈ 클래슀 λͺ©λ‘μ΄ λ…ΈμΆœλ˜λ©° 더블 클릭 μ‹œ, κ·Έλž˜ν”„μ— ν•΄λ‹Ή ν”„λž˜κ·Έλ¨ΌνŠΈκ°€ μΆ”κ°€λœλ‹€.

app:startDestination 속성은 navHost둜 μ§€μ •λœ ν•΄λ‹Ή μ•‘ν‹°λΉ„ν‹°κ°€ μ‹€ν–‰λ˜μ—ˆμ„ λ•Œ, 처음으둜 μ‹œμž‘ν•˜λŠ” 화면섀정이닀. μ•„λž˜ fragment νƒœκ·Έμ— μ •μ˜λœ id 와 동일해야 ν•œλ‹€. android:label 속성은 μ‚¬μš©μžκ°€ 읽을 수 μžˆλŠ” λŒ€μƒ 이름을 ν¬ν•¨ν•œλ‹€. 예둜 NavGraph λ₯Ό setupWithNavController()λ₯Ό μ‚¬μš©ν•˜μ—¬ Toolbar와 μ—°κ²°ν•œ 경우, UI에 ν•΄λ‹Ή 라벨 값이 ν‘œμ‹œλœλ‹€. tools:layout 속성은 ν•΄λ‹Ή ν”„λž˜κ·Έλ¨ΌνŠΈμ— λ ˆμ΄μ•„μ›ƒμ„ μ—°κ²°ν•˜μ—¬ κ·Έλž˜ν”„ ν™”λ©΄μ—μ„œ ν•΄λ‹Ή 화면을 미리보여쀄 수 μžˆλ‹€.

- ν™”λ©΄κ°„μ˜ 이동 κ΅¬ν˜„

ν”„λž˜κ·Έλ¨ΌνŠΈλ₯Ό ν•˜λ‚˜ 더 μƒμ„±ν•˜κ³ , μœ„μ™€ 같은 λ°©μ‹μœΌλ‘œ 탐색 κ·Έλž˜ν”„μ— λŒ€μƒμ„ μΆ”κ°€ν•œλ‹€.

ν”„λž˜κ·Έλ¨ΌνŠΈλ₯Ό μΆ”κ°€ν•˜κ³  Navigation Editor μ—μ„œ νŠΉμ • ν”„λž˜κ·Έλ¨ΌνŠΈλ₯Ό ν΄λ¦­ν•˜λ©΄ μœ„ 사진과 같이 였λ₯Έμͺ½ 쀑앙에 큰 동그라미가 ν‘œμ‹œλœλ‹€. ν•΄λ‹Ή λ²„νŠΌμ„ 클릭 ν•œ μ±„λ‘œ μ΄λ™ν•˜λ €λŠ” λŒ€μƒ(listFragment) 둜 λŒκ³ κ°€λ©΄ XML μ½”λ“œμ—μ„œ action μ΄λΌλŠ” νƒœκ·Έκ°€ μƒμ„±λ˜λ©° ν™”λ©΄μ „ν™˜ λŒ€μƒ 지정은 끝이닀.

이동 방법은 μ•„λž˜μ™€ κ°™λ‹€.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        Handler(Looper.getMainLooper()).postDelayed({
            // ν™”λ©΄μ΄λ™μ „ν™˜_1
            findNavController().navigate(R.id.action_homeFragment_to_listFragment2)
            // ν™”λ©΄μ΄λ™μ „ν™˜_2 todo: safe-args λ•Œ 많이 μ‚¬μš©
            val hl = HomeFragmentDirections.actionHomeFragmentToListFragment2()
            findNavController().navigate(hl)
        }, 500)
    }

ν™”λ©΄μ „ν™˜ 1λ²ˆλ°©μ‹μ€ nav_graph νŒŒμΌμ— μ •μ˜λœ μ•‘μ…˜νƒœκ·Έμ— 아이디와 λ™μΌν•˜λ‹€ ν™”λ©΄μ „ν™˜ 2λ²ˆλ°©μ‹μ€ 좔후에 μž‘μ„±ν•  safe-args κ΄€λ ¨ν•˜μ—¬ ν”ŒλŸ¬κ·ΈμΈ μ„€μ • ν›„ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€

NavDirection 은 Activity μ‹€ν–‰κ³Ό λΉ„κ΅ν•˜λ©΄ Intent 와 λΉ„μŠ·ν•˜λ‹€. κ°œλ°œμžκ°€ 직접 μ„€μ •ν•˜λŠ”κ²Œ μ•„λ‹Œ, Navigation에 μ˜ν•΄ μžλ™μœΌλ‘œ μƒμ„±λ˜λŠ” ν΄λž˜μŠ€μ΄λ‹€. μœ„ 예제 μ½”λ“œμ—μ„œ μ–ΈκΈ‰ν•œ SafeArgs λŠ” Bundle μ—μ„œ NavGraph μ„ μ–Έκ³Ό λ™μΌν•œ Type Dataλ₯Ό κ°€μ Έμ˜€λŠ” Helper둜 μƒκ°ν•˜λ©΄ λœλ‹€.

Last updated