탐색을 사용하면 대상 인수를 정의하여 탐색 작업에 데이터를 첨부할 수 있습니다. 예를 들어 사용자 프로필 대상은 사용자 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 플러그인을 사용할 수 없습니다. 이럴 때는 번들을 사용하여 직접 데이터를 전달하면 됩니다.
To add Safe Args
to your project, include the following classpath
in your top level build.gradle
file:
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") } }
You must also apply one of two available plugins.
To generate Java language code suitable for Java or mixed Java and Kotlin modules, add
this line to your app or module's build.gradle
file:
Groovy
plugins { id 'androidx.navigation.safeargs' }
Kotlin
plugins { id("androidx.navigation.safeargs") }
Alternatively, to generate Kotlin code suitable for Kotlin-only modules add:
Groovy
plugins { id 'androidx.navigation.safeargs.kotlin' }
Kotlin
plugins { id("androidx.navigation.safeargs.kotlin") }
You must have android.useAndroidX=true
in your
gradle.properties
file as per
Migrating to AndroidX.
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
...
추가 리소스
탐색에 관한 자세한 내용은 다음 추가 리소스를 참고하세요.