| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
- onStop()
- 풀리퀘스트
- onDestory()
- NavGraph
- 가시성
- arcitecture
- Bundle
- IntArray
- onResume()
- fragment
- 열거
- onCreate()
- 프래그먼트
- pullrequest
- Navgivation
- onSaveInstanceState()
- LifecycleOwner
- ViewModel
- onStart()
- Navigation Graph
- Navigation component
- 깃허브
- UI controller
- onPause()
- TransactionTooLargeException
- onRestart()
- configuration change
- Backing property
- MVVM
- LiveData
- Today
- Total
밑빠진 지식에 블로그 쓰기
Jetpack Navigation Component 본문
Android Jetpack은 앱에서 단순하거나 복잡한 어떤 탐색 구현도 처리할수 있게 도와주는 Navigation component를 제공합니다. Navigation component 주요한 3가지 부분이 있습니다.
- Navigation Graph: Navigation Graph는 앱에서 Navigation을 시각적으로 표현하는 XML파일 입니다. 이 파일은 개별 activity와 fragment에 해당하는 destination(목적지)와 한 목적지에서 다른 목적지로 이동하는 코드에서 사용되는 그들사이의 작업으로 구성됩니다. 레이아웃 파일과 마찬가지고 네비게이션 destination과 action을 추가하는 편집기를 제공합니다.
- NavHost: NavHost는 activity내에서 네비게이션 그래프에서 목적지를 보여주는데 사용됩니다. 프래그먼트 사이를 이동하면 NavHost에 보이는 목적지가 업데이트 됩니다. 엑티비티에서 NavHostFragment라는 내장 구현을 사용합니다.
- NavController : NavController 객체를 사용하면 NavHost에 표시된 목적지간의 이동을 제어할 수 있습니다.
인텐트로 작업할때 우리는 새화면으로 이동하기 위해 startActivity를 호출 해야 했다. Navigation Component를 사용하면
NavController의 navigate()메소드를 호출해서 보여지는 프래그먼트를 교체 할수 있다. 또, NavController 이전에 표시된 프래그먼트로 다시 이동하기 위해 시스템 up 버튼에 대응하는 것과 같은 흔한 작업을 처리하는데 도움이 됩니다.
Dependency setup
project-level build.gradle
buildscript {
ext {
appcompat_version = "1.5.1"
constraintlayout_version = "2.1.4"
core_ktx_version = "1.9.0"
kotlin_version = "1.7.10"
material_version = "1.7.0-alpha2"
nav_version = "2.5.2"
}
...
}
app-level build.gradle
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
Safe Args Plugin
두 엑티비티 사이에 명시적 인텐트를 사용했다. 두 엑티비티 간의 데이터를 전달 하기위해 우리는 putExtra() 메소드를 사용하고 데이터를 전달 했다. 프래그먼트 간에 데이터를 전달할때 type safety(타입 안정성)을 지원하는 Gradle 플러그인인 Safe Args라는 항목도 추가 합니다.
Setup
project-level build.gradle
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
app-level build.gradle
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'androidx.navigation.safeargs.kotlin'
}
Navigation Graph 사용하기
Navigation component는 간단하게 프래그먼트 간의 이동을 구현하기위한 도구 모음 입니다. 이 도구는 안드로이드 스튜디오 에서 제공하는 편집기로 작업하게 됩니다. 바로 Navigation Graph ( 짧게 NavGraph).
NavGraph는 앱 이동의 가상의 매핑입니다. 각화면, 각 프래그먼트는 이동할수 있는 목적지가 됩니다. NavGraph는 각 목적지가 서로 어떻게 관련되어 있는지를 보여주는 XML파일로 나타난다.
내부적으로 실제로 NavGraph 클래스의 새로운 인스턴스를 생성합니다.
NavGraph로부터 목적지는 FragmentContainerView에 의해 유저에게 표시 됩니다.
너가 할일은 XML파일을 만들고 접근할수 있는 목적지를 정의하기만 하며 된다.
그런 다음 생성된 코드를 사용하여 프래그먼트간 이동을 할수있다.
FragmentContainerView 사용하기
엑티비티에서 프래그먼트를 표시하기 위해서 FragmentContainerView를 사용해야한다.
FragmentContainerView사용하면 이제 앱의 모든 이동은 FragmentContainerView내에서 이루어 진다.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
Navigation Graph 설정
File > New > Android Resource File
File name : nav_graph.xml , 이건 이전에 설정한 app:navGraph="@navigation/nav_graph" 값과 같다.
Navigatino action 생성
두 프래그먼트 사이의 action 을 생성하기 위해 드래그로 연결.
화살표가 생성 된다. 화살표의 id 속성은 action_시작_to_도착
이동할 프래그먼트로 넘길 인자 명시하기. ( 인텐트의 putExtra)
네비게이션 또한 목적지 간의 매개변수 전달을 지원하고, 타입이 안전한 방식으로 이 작업을 수행 할 수 있다.
목적지 프래그먼트를 선택하고 Arguments 속성 창에 더하기를 클릭
이것은 이전에 추가한 Safe Args 플러그인이 들어오는 곳입니다. 이 인자를 문자열로 지정하면 이동 action 코드에서 문자열이 오는것이 예상됩니다.
시작 목적지 설정
NavGraph는 필요한 모든 대상을 알고 있지만 FragmentContainerView는 어떤 조각을 먼저 표시할지 어떻게 알 수 있습니까? NavGraph에서 문자 목록을 시작 대상으로 설정해야 합니다. NavGraph xml파일에서 목적지를 선택하고 집모양 버튼을 누르면 시작 목적지로 설정된다.
Naviagtion Action 수행하기
val action = LetterListFragmentDirections.actionLetterListFragmentToWordListFragment(letter = holder.button.text.toString())
이러한 클래스 및 함수 이름 중 일부는 프로젝트를 빌드한 후 자동으로 생성되었기 때문에 인식하지 못할 수 있습니다. 여기에서 첫 번째 단계에서 추가한 Safe Args 플러그인이 제공됩니다. NavGraph에서 생성된 작업은 사용할 수 있는 코드로 변환됩니다. 그러나 이름은 상당히 직관적이어야 합니다. LetterListFragmentDirections를 사용하면 letterListFragment에서 시작하는 가능한 모든 탐색 경로를 참조할 수 있습니다. actionLetterListFragmentToWordListFragment() 함수 wordListFragment로 이동하기 위한 특정 작업입니다.
navigation action 에 대한 참조가 있으면 NavController(navigation action 을 수행할 수 있는 객체)에 대한 참조를 가져오고action 매개변수에에 전달하는 navigate()를 호출합니다.
holder.view.findNavController().navigate(action)
Activity 구성
1. navController 속성 생성. 이 속성은 onCreate에서 설정 되기 떄문에 lateinit으로 표시
private lateinit var navController: NavController
2.
onCreate()에서 setContentView()호출 이후에 FragmentContainView참조 하고 navController 속성에 할당
val navHostFragment = supportFragmentManager
.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController
3. onCreate()에서 navController 를 넘기고 setupActionBarWithNavController() 호출. 이렇게 하면 LetterListFragment의 메뉴 옵션과 같은 작업 표시줄(앱 표시줄) 버튼이 표시됩니다.
setupActionBarWithNavController(navController)
4. 마지막으로 onSupportNavigateUp() 구현. XML에서 defaultNavHost를 true로 설정하는 것과 함께 이 메서드를 사용하면 위로 버튼을 처리할 수 있습니다. 그러나 엑티비티에서 구현을 제공해야 합니다.
또, nav_graph를 사용하여 이동을 수행하고 Safe arguments를 사용하는 경우 인텐트가 없으므로 extra에 접근하는 시도는 간단하기 작동하지 않는다.
고맙게도 안전한 인수에 액세스하는 것은 매우 간단하며 onViewCreated()가 호출될 때까지 기다릴 필요도 없습니다.
1. WordListFragment에서 letterId 속성을 만듭니다. nullable로 만들 필요가 없도록 lateinit로 표시할 수 있습니다.
private lateinit var letterId: String
2.그런 다음 onCreate()(onCreateView() 또는 onViewCreated()가 아님!)를 재정의하고 다음을 추가합니다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
letterId = it.getString(LETTER).toString()
}
}
인수가 선택 사항일 수 있으므로 let()을 호출하고 람다를 전달합니다. 이 코드는 인수가 null이 아니라고 가정하고 it 매개 변수에 대해 null이 아닌 인수를 전달하여 실행합니다. 그러나 인수가 null이면 람다는 실행되지 않습니다.
Bundle
번들이란 정확히 무엇입니까? 액티비티 및 프래그먼트와 같은 클래스 간에 데이터를 전달하는 데 사용되는 키-값 쌍으로 생각하십시오. 사실 이 앱의 첫 번째 버전에서 인텐트를 수행할 때 intent?.extras?.getString()을 호출했을 때 이미 번들을 사용했습니다. 프래그먼트로 작업할 때 인수에서 문자열을 가져오는 것은 정확히 같은 방식으로 작동합니다.
마지막으로 recycler view의 어댑터를 설정할 때 letterId에 액세스할 수 있습니다. onViewCreated()의 activity?.intent?.extras?.getString(LETTER).toString()을 letterId로 바꿉니다.
참고
프래그먼트 및 탐색 구성요소 | Android 개발자 | Android Developers
이 Codelab에서는 프래그먼트를 사용하고 단일 활동 내에서 탐색을 구현하도록 Words 앱을 변환하면서 프래그먼트, 프래그먼트 수명 주기, Jetpack의 탐색 구성요소를 알아봅니다.
developer.android.com
https://www.youtube.com/watch?v=xITkfPIaStU
테스트
탐색 구성요소 테스트 | Android Developers
이 Codelab에서는 탐색 구성요소에서 처리되는 탐색을 테스트하는 방법을 알아봅니다. 테스트에서 코드 반복을 줄이는 방법도 알아봅니다.
developer.android.com