Dynamic Navigator 라이브러리는 기능 모듈에 정의된 대상과 함께 작동하도록 Jetpack 탐색 구성요소의 기능을 확장합니다. 또한 이 라이브러리를 사용하면 이러한 대상으로 이동할 때 주문형 기능 모듈을 원활하게 설치할 수 있습니다.
설정
기능 모듈을 지원하려면 앱 모듈의 build.gradle
파일에 다음 종속 항목을 사용합니다.
Groovy
dependencies { def nav_version = "2.7.7" api "androidx.navigation:navigation-fragment-ktx:$nav_version" api "androidx.navigation:navigation-ui-ktx:$nav_version" api "androidx.navigation:navigation-dynamic-features-fragment:$nav_version" }
Kotlin
dependencies { val nav_version = "2.7.7" api("androidx.navigation:navigation-fragment-ktx:$nav_version") api("androidx.navigation:navigation-ui-ktx:$nav_version") api("androidx.navigation:navigation-dynamic-features-fragment:$nav_version") }
다른 탐색 종속 항목은 API 구성을 사용해야 합니다. 이러한 API를 기능 모듈에서 사용할 수 있습니다
기본 사용법
기능 모듈을 지원하려면 다음과 같이 먼저, 앱의 모든 NavHostFragment
인스턴스를 androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment
로 변경합니다.
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment"
app:navGraph="@navigation/nav_graph"
... />
다음으로, DynamicNavHostFragment
와 연결된 com.android.dynamic-feature
탐색 그래프의 <activity>
, <fragment>
또는 <navigation>
대상에 app:moduleName
속성을 추가합니다.
이 속성은 대상이 개발자가 지정한 이름의 기능 모듈에 속함을 Dynamic Navigator 라이브러리에 알려줍니다.
<fragment
app:moduleName="myDynamicFeature"
android:id="@+id/featureFragment"
android:name="com.google.android.samples.feature.FeatureFragment"
... />
이러한 대상 중 하나로 이동할 때 Dynamic Navigator 라이브러리는 먼저, 기능 모듈이 설치되어 있는지 확인합니다. 기능 모듈이 이미 있다면 앱은 예상대로 대상으로 이동합니다. 모듈이 없다면 앱은 모듈을 설치할 때 중간 진행률 프래그먼트 대상을 표시합니다. 진행률 프래그먼트의 기본 구현은 진행률 표시줄이 있는 기본 UI를 표시하고 모든 설치 오류를 처리합니다.
![기능 모듈로 처음 이동할 때 진행률 표시줄이 있는 UI를 표시하는 로드 화면 2개](https://developer.android.com/static/images/guide/navigation/dfm-nav-loading.png?authuser=9&hl=ko)
이 UI를 맞춤설정하거나 자체 앱 화면 내에서 설치 진행률을 수동으로 처리하려면 이 주제의 진행률 프래그먼트 맞춤설정 및 요청 상태 모니터링 섹션을 참고하세요.
app:moduleName
을 지정하지 않은 대상은 변경 없이 계속 작동하며 앱이 일반 NavHostFragment
를 사용하는 것처럼 동작합니다.
진행률 프래그먼트 맞춤설정
app:progressDestination
속성을 설치 진행률 처리에 사용할 대상의 ID로 설정하여 각 탐색 그래프의 진행률 프래그먼트 구현을 재정의할 수 있습니다. 맞춤 진행률 대상은 AbstractProgressFragment
에서 파생된 Fragment
여야 합니다.
설치 진행률, 오류 및 기타 이벤트에 관한 알림을 위해 추상 메서드를 재정의해야 합니다. 그러면 직접 선택한 UI에 설치 진행률을 표시할 수 있습니다.
기본 구현의 DefaultProgressFragment
클래스는 이 API를 사용하여 설치 진행률을 표시합니다.
요청 상태 모니터링
Dynamic Navigator 라이브러리를 사용하면 주문형 제공을 위한 UX 권장사항의 흐름과 유사한 UX 흐름을 구현할 수 있습니다. 여기서 사용자는 설치가 완료될 때까지 기다리는 동안 이전 화면의 컨텍스트에 유지됩니다. 즉, 중간 UI 또는 진행률 프래그먼트를 전혀 표시할 필요가 없습니다.
![기능 모듈이 다운로드 중임을 나타내는 아이콘이 있는 하단 탐색 메뉴를 표시하는 화면](https://developer.android.com/static/images/guide/navigation/nav-dfm-ui.png?authuser=9&hl=ko)
이 시나리오에서는 개발자가 모든 설치 상태, 진행률 변경, 오류 등을 모니터링하고 처리해야 합니다.
이 비차단 탐색 흐름을 시작하려면 다음 예와 같이 DynamicInstallMonitor
가 포함된 DynamicExtras
객체를 NavController.navigate()
에 전달합니다.
Kotlin
val navController = ... val installMonitor = DynamicInstallMonitor() navController.navigate( destinationId, null, null, DynamicExtras(installMonitor) )
자바
NavController navController = ... DynamicInstallMonitor installMonitor = new DynamicInstallMonitor(); navController.navigate( destinationId, null, null, new DynamicExtras(installMonitor); )
navigate()
를 호출한 직후 installMonitor.isInstallRequired
값을 확인하여 시도된 탐색으로 인해 기능 모듈이 설치되었는지 확인해야 합니다.
- 값이
false
이면 일반 대상으로 이동하는 중이며 다른 작업을 할 필요가 없습니다. 값이
true
이면 현재installMonitor.status
에 있는LiveData
객체 관찰을 시작해야 합니다. 이LiveData
객체는 Play Core 라이브러리에서SplitInstallSessionState
업데이트를 내보냅니다. 이러한 업데이트에는 UI를 업데이트하는 데 사용할 수 있는 설치 진행 상황 이벤트가 포함됩니다. 필요한 경우 사용자 확인 요청을 포함하여 Play Core 가이드에서 설명한 모든 관련 상태를 처리해야 합니다.Kotlin
val navController = ... val installMonitor = DynamicInstallMonitor() navController.navigate( destinationId, null, null, DynamicExtras(installMonitor) ) if (installMonitor.isInstallRequired) { installMonitor.status.observe(this, object : Observer<SplitInstallSessionState> { override fun onChanged(sessionState: SplitInstallSessionState) { when (sessionState.status()) { SplitInstallSessionStatus.INSTALLED -> { // Call navigate again here or after user taps again in the UI: // navController.navigate(destinationId, destinationArgs, null, null) } SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION -> { SplitInstallManager.startConfirmationDialogForResult(...) } // Handle all remaining states: SplitInstallSessionStatus.FAILED -> {} SplitInstallSessionStatus.CANCELED -> {} } if (sessionState.hasTerminalStatus()) { installMonitor.status.removeObserver(this); } } }); }
자바
NavController navController = ... DynamicInstallMonitor installMonitor = new DynamicInstallMonitor(); navController.navigate( destinationId, null, null, new DynamicExtras(installMonitor); ) if (installMonitor.isInstallRequired()) { installMonitor.getStatus().observe(this, new Observer<SplitInstallSessionState>() { @Override public void onChanged(SplitInstallSessionState sessionState) { switch (sessionState.status()) { case SplitInstallSessionStatus.INSTALLED: // Call navigate again here or after user taps again in the UI: // navController.navigate(mDestinationId, mDestinationArgs, null, null); break; case SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION: SplitInstallManager.startConfirmationDialogForResult(...) break; // Handle all remaining states: case SplitInstallSessionStatus.FAILED: break; case SplitInstallSessionStatus.CANCELED: break; } if (sessionState.hasTerminalStatus()) { installMonitor.getStatus().removeObserver(this); } } }); }
설치가 완료되면 LiveData
객체가 SplitInstallSessionStatus.INSTALLED
상태를 내보냅니다. 그러면 NavController.navigate()
를 다시 호출해야 합니다. 이제 모듈이 설치되었으므로 호출이 성공하고 앱이 예상대로 대상으로 이동합니다.
설치가 완료되거나 설치가 실패한 때와 같은 최종적인 상태에 도달한 이후에는 메모리 누수를 방지하기 위해 LiveData
관찰자를 삭제해야 합니다. SplitInstallSessionStatus.hasTerminalStatus()
를 사용하면 상태가 최종적인 상태를 나타내는지 확인할 수 있습니다.
이 관찰자의 구현 예는 AbstractProgressFragment
를 참고하세요.
포함된 그래프
Dynamic Navigator 라이브러리는 기능 모듈에 정의된 그래프 포함을 지원합니다. 기능 모듈에 정의된 그래프를 포함하려면 다음 단계를 따르세요.
다음 예와 같이
<include/>
대신<include-dynamic/>
을 사용합니다.<include-dynamic android:id="@+id/includedGraph" app:moduleName="includedgraphfeature" app:graphResName="included_feature_nav" app:graphPackage="com.google.android.samples.dynamic_navigator.included_graph_feature" />
<include-dynamic ... />
내에서 다음 속성을 지정해야 합니다.app:graphResName
- 탐색 그래프 리소스 파일의 이름입니다. 이름은 그래프의 파일 이름에서 파생됩니다. 예를 들어 그래프가res/navigation/nav_graph.xml
에 있다면 리소스 이름은nav_graph
입니다.android:id
- 그래프 대상 ID입니다. Dynamic Navigator 라이브러리는 포함된 그래프의 루트 요소에 있는android:id
값을 무시합니다.app:moduleName
: 모듈의 패키지 이름입니다.
올바른 graphPackage 사용
다른 경우에는 탐색 구성요소가 기능 모듈에서 지정된 navGraph
를 포함할 수 없으므로 app:graphPackage
를 정확하게 설정하는 것이 중요합니다.
동적 기능 모듈의 패키지 이름은 모듈 이름을 기본 앱 모듈의 applicationId
에 추가하여 구성됩니다. 따라서 기본 앱 모듈의 applicationId
가 com.example.dynamicfeatureapp
이고 동적 기능 모듈의 이름이 DynamicFeatureModule
이라면 동적 모듈의 패키지 이름은 com.example.dynamicfeatureapp.DynamicFeatureModule
이 됩니다. 이 패키지 이름은 대소문자를 구분합니다.
확실하지 않은 경우 생성된 AndroidManifest.xml
을 확인하여 기능 모듈의 패키지 이름을 확인할 수 있습니다. 프로젝트를 빌드한 후에는 다음과 같이 표시되는 <DynamicFeatureModule>/build/intermediates/merged_manifest/debug/AndroidManifest.xml
로 이동합니다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:dist="http://schemas.android.com/apk/distribution" featureSplit="DynamicFeatureModule" package="com.example.dynamicfeatureapp" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" /> <dist:module dist:instant="false" dist:title="@string/title_dynamicfeaturemodule" > <dist:delivery> <dist:install-time /> </dist:delivery> <dist:fusing dist:include="true" /> </dist:module> <application /> </manifest>
featureSplit
값은 동적 기능 모듈의 이름과 일치해야 하고 패키지는 기본 앱 모듈의 applicationId
와 일치합니다. app:graphPackage
는 다음과 같은 조합입니다. com.example.dynamicfeatureapp.DynamicFeatureModule
include-dynamic 탐색 그래프로 이동
include-dynamic
탐색 그래프의 startDestination
으로만 이동할 수 있습니다. 동적 모듈은 자체 탐색 그래프를 담당하고 기본 앱은 이를 인식하지 못합니다.
include-dynamic 메커니즘을 사용하면 기본 앱 모듈이 동적 모듈 내에 정의된 중첩된 탐색 그래프를 포함할 수 있습니다. 이 중첩된 탐색 그래프는 다른 중첩된 탐색 그래프처럼 동작합니다. 루트 탐색 그래프 (즉, 상위 탐색 그래프
)는 중첩된 탐색 그래프 자체만
대상이며 하위 요소가 아닙니다. 따라서 startDestination
은 include-dynamicnavigation 그래프가 대상일 때 사용됩니다.
제한사항
- 동적으로 포함된 그래프는 현재 딥 링크를 지원하지 않습니다.
- 동적으로 로드된 중첩 그래프(즉,
app:moduleName
이 있는<navigation>
요소)는 현재 딥 링크를 지원하지 않습니다.