탐색을 사용하면 대상 인수를 정의하여 탐색 작업에 데이터를 첨부할 수 있습니다. 예를 들어 사용자 프로필 대상은 사용자 ID 인수를 취해 표시할 사용자를 결정할 수 있습니다.
일반적으로 대상 간에 최소한의 데이터만 전달하는 것이 좋습니다. 예를 들어 객체 자체를 전달하지 않고 키를 전달하여 객체를 검색해야 하는데 이는 모든 저장된 상태의 총 공간이 Android에서 제한되기 때문입니다. 대량의 데이터를 전달해야 하는 경우 ViewModel 개요에 설명된 대로 ViewModel
을 사용하세요.
대상 인수 정의
대상 간에 데이터를 전달하려면 먼저 다음 단계에 따라 인수를 받는 대상에 추가하여 인수를 정의합니다.
- Navigation Editor에서 인수를 받는 대상을 클릭합니다.
- Attributes 패널에서 Add(+)를 클릭합니다.
- 표시되는 Add Argument Link 창에서 인수 이름과 인수 유형, 인수의 null 허용 여부 그리고 필요하다면 기본값을 입력합니다.
- Add를 클릭합니다. 이제 Attributes 패널의 Arguments 목록에 인수가 표시됩니다.
- 그런 다음 대상으로 이동하게 하는 작업을 클릭합니다. Attributes 패널에서 이제는 Argument Default Values 섹션에 새롭게 추가된 인수가 표시됩니다.
또한 인수가 XML에 추가된 것을 알 수 있습니다. Text 탭을 클릭하여 XML 뷰로 전환하면 인수가 인수를 받는 대상에 추가된 것을 확인할 수 있습니다. 아래 예를 참고하세요.
<fragment android:id="@+id/myFragment" > <argument android:name="myArg" app:argType="integer" android:defaultValue="0" /> </fragment>
지원되는 인수 유형
탐색 라이브러리는 다음 인수 유형을 지원합니다.
유형 | app:argType 문법 | 기본값 지원 | 경로에서 처리됨 | Null 허용됨 |
---|---|---|---|---|
정수 | app:argType="integer" | 예 | 예 | 아니요 |
Float | app:argType="float" | 예 | 예 | 아니요 |
Long | app:argType="long" | 예 - 기본값은 항상 'L' 접미사로 끝나야 합니다(예: '123L'). | 예 | 아니요 |
부울 | app:argType="boolean" | 예 - 'true' 또는 'false' | 예 | 아니요 |
문자열 | app:argType="string" | 예 | 예 | 예 |
리소스 참조 | app:argType="reference" | 예 - 기본값은 '@resourceType/resourceName'(예: '@style/myCustomStyle') 형식이나 '0'이어야 합니다. | 예 | 아니요 |
맞춤 Parcelable | app:argType="<type>", 여기서 <type>은 Parcelable 의 정규화된 클래스 이름입니다. |
기본값 '@null'을 지원합니다. 다른 기본값은 지원하지 않습니다. | 아니요 | 예 |
맞춤 Serializable | app:argType="<type>", 여기서 <type>은 Serializable 의 정규화된 클래스 이름입니다. |
기본값 '@null'을 지원합니다. 다른 기본값은 지원하지 않습니다. | 아니요 | 예 |
맞춤 Enum | app:argType="<type>", 여기서 <type>은 enum의 정규화된 이름입니다. | 예 - 기본값은 정규화되지 않은 이름과 일치해야 합니다(예: 'SUCCESS'가 MyEnum.SUCCESS와 일치). | 아니요 | 아니요 |
인수 유형이 null 값을 지원하는 경우 android:defaultValue="@null"
을 사용하여 기본값을 null로 선언할 수 있습니다.
경로, 딥 링크 및 인수가 포함된 URI를 문자열에서 파싱할 수 있습니다. 위의 표에서 보는 바와 같이 Parcelable 및 Serializable과 같은 맞춤 데이터 유형은 사용할 수 없습니다. 맞춤 복합 데이터를 전달하려면 ViewModel 또는 데이터베이스와 같은 다른 위치에 데이터를 저장하고 탐색 중에 식별자만 전달한 다음 탐색이 완료된 후 새로운 위치에서 데이터를 회수합니다.
맞춤 유형 중 하나를 선택하면 Select Class 대화상자가 표시되고 선택한 유형에 상응하는 클래스를 선택하라는 메시지가 표시됩니다. Project 탭을 사용하면 현재 프로젝트에서 클래스를 선택할 수 있습니다.
<inferred type>을 선택하여 제공된 값에 기반해 탐색 라이브러리가 유형을 결정하도록 할 수 있습니다.
Array를 확인하여 인수가 선택된 Type 값의 배열이어야 함을 나타낼 수 있습니다. 다음 내용을 참고하세요.
- enum 배열과 리소스 참조 배열은 지원되지 않습니다.
- 기본 유형이 null을 허용하는 값을 지원하는지와 상관없이 배열은 null을 허용하는 값을 지원합니다. 예를 들어
app:argType="integer[]"
를 사용하면app:nullable="true"
를 사용하여 null 배열을 전달할 수 있음을 나타낼 수 있습니다. - 배열은 단일 기본값 '@null'을 지원합니다. 배열은 다른 기본값을 지원하지 않습니다.
작업에서 대상 인수 재정의
대상 레벨 인수 및 기본값은 대상을 탐색하는 모든 작업에서 사용됩니다. 필요한 경우 작업 레벨에서 인수를 정의하여 인수의 기본값을 재정의하거나 존재하지 않는 경우 설정할 수 있습니다. 이 인수는 대상에서 선언된 인수와 동일한 이름과 유형이어야 합니다.
다음 XML은 이전 예의 대상 수준 인수를 재정의하는 인수로 작업을 선언합니다.
<action android:id="@+id/startMyFragment"
app:destination="@+id/myFragment">
<argument
android:name="myArg"
app:argType="integer"
android:defaultValue="1" />
</action>
Safe Args를 사용하여 유형 안전성을 갖춘 데이터 전달
탐색 구성요소에는 Safe Args라는 Gradle 플러그인이 있어서 모든 연결된 인수에 유형 안전성을 갖춘 탐색 및 액세스를 하기 위한 간단한 객체 및 빌더 클래스를 생성합니다. Safe Args는 유형 안전성을 보장하므로 데이터를 탐색하고 전달할 때는 Safe Args를 사용하는 것이 좋습니다.
Gradle을 사용하지 않으면 Safe Args 플러그인을 사용할 수 없습니다. 이럴 때는 번들을 사용하여 직접 데이터를 전달하면 됩니다.
프로젝트에 Safe Args를 추가하려면 최상위 build.gradle
파일에 다음의 classpath
를 포함합니다.
Groovy
buildscript { repositories { google() } dependencies { def nav_version = "2.8.4" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" } }
Kotlin
buildscript { repositories { google() } dependencies { val nav_version = "2.8.4" classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version") } }
또한 사용 가능한 두 가지 플러그인 중 하나를 적용해야 합니다.
자바 모듈 또는 자바와 Kotlin 혼합 모듈에 적합한 자바 언어 코드를 생성하려면 앱 또는 모듈의 build.gradle
파일에 다음 행을 추가합니다.
Groovy
plugins { id 'androidx.navigation.safeargs' }
Kotlin
plugins { id("androidx.navigation.safeargs") }
또는 Kotlin 전용 모듈에 적합한 Kotlin 코드를 생성하려면 다음을 추가하세요.
Groovy
plugins { id 'androidx.navigation.safeargs.kotlin' }
Kotlin
plugins { id("androidx.navigation.safeargs.kotlin") }
AndroidX로 이전에 따라 gradle.properties
파일에 android.useAndroidX=true
가 있어야 합니다.
Safe Args를 사용 설정한 후 생성된 코드에는 각 송수신 대상과 함께 각 작업의 다음과 같은 유형 안전 클래스와 메서드가 포함됩니다.
작업이 시작되는 각 대상에 클래스가 만들어집니다. 클래스 이름은 'Directions'라는 단어가 추가된 발신 대상의 이름입니다. 예를 들어 발신 대상이
SpecifyAmountFragment
라는 이름의 프래그먼트라면 생성된 클래스의 이름은SpecifyAmountFragmentDirections
입니다.이 클래스에는 발신 대상에서 정의된 각 작업의 메서드가 있습니다.
인수를 전달하는 데 사용되는 각 작업의 경우 작업에 기반한 이름으로 내부 클래스가 만들어집니다. 예를 들어 작업 이름이
confirmationAction,
이라면 클래스 이름은ConfirmationAction
입니다. 작업에defaultValue
가 없는 인수가 포함되면 관련된 작업 클래스를 사용하여 인수 값을 설정합니다.수신 대상에 클래스가 만들어집니다. 클래스 이름은 'Args'라는 단어가 추가된 대상 이름입니다. 예를 들어 대상 프래그먼트 이름이
ConfirmationFragment,
라면 생성된 클래스 이름은ConfirmationFragmentArgs
입니다. 이 클래스의fromBundle()
메서드를 사용하여 인수를 검색하세요.
다음 예에서는 이러한 메서드를 사용하여 인수를 설정하고 navigate()
메서드에 전달하는 방법을 보여줍니다.
Kotlin
override fun onClick(v: View) { val amountTv: EditText = view!!.findViewById(R.id.editTextAmount) val amount = amountTv.text.toString().toInt() val action = SpecifyAmountFragmentDirections.confirmationAction(amount) v.findNavController().navigate(action) }
Java
@Override public void onClick(View view) { EditText amountTv = (EditText) getView().findViewById(R.id.editTextAmount); int amount = Integer.parseInt(amountTv.getText().toString()); ConfirmationAction action = SpecifyAmountFragmentDirections.confirmationAction(); action.setAmount(amount); Navigation.findNavController(view).navigate(action); }
수신 대상 코드에서 getArguments()
메서드를 사용하여 번들을 검색하고 그 콘텐츠를 사용합니다. -ktx
종속 항목을 사용할 때 Kotlin 사용자는 by navArgs()
속성 위임을 사용하여 인수에 액세스할 수도 있습니다.
Kotlin
val args: ConfirmationFragmentArgs by navArgs() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val tv: TextView = view.findViewById(R.id.textViewAmount) val amount = args.amount tv.text = amount.toString() }
Java
@Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { TextView tv = view.findViewById(R.id.textViewAmount); int amount = ConfirmationFragmentArgs.fromBundle(getArguments()).getAmount(); tv.setText(amount + ""); }
전역 작업으로 Safe Args 사용
전역 작업으로 Safe Args를 사용할 때 다음 예와 같이 루트 <navigation>
요소에 android:id
값을 제공해야 합니다.
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_nav" app:startDestination="@id/mainFragment"> ... </navigation>
탐색은 android:id
값에 기반한 <navigation>
요소의 Directions
클래스를 생성합니다. 예를 들어 android:id=@+id/main_nav
값이 있는 <navigation>
요소가 있다면 생성된 클래스 이름은 MainNavDirections
가 됩니다. <navigation>
요소 내의 모든 대상은 이전 섹션에서 설명한 것과 동일한 메서드를 사용하여 관련된 모든 전역 작업에 액세스하는 메서드를 생성했습니다.
번들 객체로 대상 간 데이터 전달
Gradle을 사용하지 않는 경우 Bundle
객체를 사용하여 대상 간에 계속 인수를 전달할 수 있습니다. 다음 예와 같이 Bundle
객체를 만들고 navigate()
를 사용하여 대상에 전달합니다.
Kotlin
val bundle = bundleOf("amount" to amount) view.findNavController().navigate(R.id.confirmationAction, bundle)
Java
Bundle bundle = new Bundle(); bundle.putString("amount", amount); Navigation.findNavController(view).navigate(R.id.confirmationAction, bundle);
수신 대상 코드에서 getArguments()
메서드를 사용하여 Bundle
을 검색하고 그 콘텐츠를 사용하세요.
Kotlin
val tv = view.findViewById<TextView>(R.id.textViewAmount) tv.text = arguments?.getString("amount")
자바
TextView tv = view.findViewById(R.id.textViewAmount); tv.setText(getArguments().getString("amount"));
시작 대상에 데이터 전달
앱의 시작 대상에 데이터를 전달할 수 있습니다. 먼저 데이터를 보유하는 Bundle
을 명시적으로 구성해야 합니다. 그리고 다음 방법 중 하나를 사용하여 Bundle
을 시작 대상에 전달합니다.
- 프로그래매틱 방식으로
NavHost
를 만드는 경우NavHostFragment.create(R.navigation.graph, args)
를 호출하세요. 여기서args
는 데이터를 보유하는Bundle
입니다. - 그렇지 않은 경우
NavController.setGraph()
의 다음 오버로드 중 하나를 호출하여 시작 대상 인수를 설정할 수 있습니다.- 그래프의 ID를 사용합니다.
navController.setGraph(R.navigation.graph, args)
- 그래프 자체를 사용합니다.
navController.setGraph(navGraph, args)
- 그래프의 ID를 사용합니다.
시작 대상에서 데이터를 검색하려면 Fragment.getArguments()
를 호출합니다.
ProGuard 고려사항
코드를 축소하는 경우 Parcelable
, Serializable
, Enum
클래스 이름이 압축 처리의 일환으로 난독화되지 않도록 해야 합니다. 다음 두 가지 방법 중 하나로 이 작업을 실행할 수 있습니다.
- @Keep 주석 사용
- keepnames 규칙 사용
다음 하위 섹션에서는 이러한 접근 방식을 설명합니다.
@Keep 주석 사용
다음 예에서는 모델 클래스 정의에 @Keep
주석을 추가합니다.
Kotlin
@Keep class ParcelableArg : Parcelable { ... } @Keep class SerializableArg : Serializable { ... } @Keep enum class EnumArg { ... }
자바
@Keep public class ParcelableArg implements Parcelable { ... } @Keep public class SerializableArg implements Serializable { ... } @Keep public enum EnumArg { ... }
keepnames 규칙 사용
또한 다음 예에서와 같이 keepnames
규칙을 proguard-rules.pro
파일에 추가할 수도 있습니다.
proguard-rules.pro
...
-keepnames class com.path.to.your.ParcelableArg
-keepnames class com.path.to.your.SerializableArg
-keepnames class com.path.to.your.EnumArg
...
추가 리소스
탐색에 관한 자세한 내용은 다음 추가 리소스를 참고하세요.