탐색 그래프는 다음을 원하는 대로 조합하여 구성할 수 있습니다.
이러한 유연성을 통해 작은 탐색 그래프를 함께 결합하여 앱의 완전한 탐색 그래프를 구성할 수 있습니다. 이러한 작은 탐색 그래프가 별도의 모듈에서 제공되더라도 마찬가지입니다.
이 주제의 예에서는 각각
기능 모듈에서는
하나의 특성과
모든 대상을 캡슐화하는 단일 탐색 그래프를 제공합니다.
이 기능을 구현하는 데 필요합니다. 프로덕션 앱에는 이 상위 수준 기능 모듈의 구현 세부정보인 하위 모듈이 하위 수준에 여러 개 있을 수 있습니다. 이러한 각 기능 모듈은 직접 또는 간접적으로 app
모듈에 포함됩니다. 이 문서에 사용된 다중 모듈 애플리케이션 예의 구조는 다음과 같습니다.
![샘플 다중 모듈 애플리케이션의 종속 항목 그래프](https://developer.android.com/static/images/guide/navigation/multimodule-structure.png?authuser=9&hl=ko)
![예시 앱의 시작 대상](https://developer.android.com/static/images/guide/navigation/multimodule-screen.png?authuser=9&hl=ko)
각 기능 모듈은 자체 탐색 그래프와 대상이 있는 독립된 단위입니다. app
모듈은 각각에 종속되므로 다음과 같이 build.gradle
파일에 구현 세부정보로 추가됩니다.
Groovy
dependencies { ... implementation project(":feature:home") implementation project(":feature:favorites") implementation project(":feature:settings")
Kotlin
dependencies { ... implementation(project(":feature:home")) implementation(project(":feature:favorites")) implementation(project(":feature:settings"))
app
모듈의 역할
app
모듈은 앱의 완전한 그래프를 제공하고 NavHost
를 UI에 추가합니다. app
모듈의 탐색 그래프 내에서 <include>
를 사용하여 라이브러리 그래프를 참조할 수 있습니다. <include>
사용은 기능적으로 중첩 그래프를 사용하는 것과 같지만 <include>
는 다음 예와 같이 다른 프로젝트 모듈 또는 라이브러리 프로젝트의 그래프를 지원합니다.
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/nav_graph"
app:startDestination="@id/home_nav_graph">
<include app:graph="@navigation/home_navigation" />
<include app:graph="@navigation/favorites_navigation" />
<include app:graph="@navigation/settings_navigation" />
</navigation>
라이브러리가 최상위 탐색 그래프에 포함되면 필요에 따라 라이브러리 그래프로 이동할 수 있습니다. 예를 들어 다음과 같이 탐색 그래프의 프래그먼트에서 설정 그래프로 이동하는 작업을 만들 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/nav_graph"
app:startDestination="@id/home_nav_graph">
<include app:graph="@navigation/home_navigation" />
<include app:graph="@navigation/favorites_navigation" />
<include app:graph="@navigation/settings_navigation" />
<fragment
android:id="@+id/random_fragment"
android:name="com.example.android.RandomFragment"
android:label="@string/fragment_random" >
<!-- Launch into Settings Navigation Graph -->
<action
android:id="@+id/action_random_fragment_to_settings_nav_graph"
app:destination="@id/settings_nav_graph" />
</fragment>
</navigation>
여러 기능 모듈이 로그인 그래프와 같은 일반적인 대상 집합을 참조해야 하는 경우 이러한 일반적인 대상을 각 기능 모듈의 탐색 그래프에 포함하면 안 됩니다. 대신 이러한 일반적인 대상을 app
모듈의 탐색 그래프에 추가하세요.
그런 다음 각 기능 모듈은 기능 모듈 전체를 탐색하여 이러한 일반적인 대상으로 이동할 수 있습니다.
이전 예에서 작업은 @id/settings_nav_graph
의 탐색 대상을 지정합니다. 이 ID는 포함된 그래프 @navigation/settings_navigation.
내에서 정의된 대상을 나타냅니다.
앱 모듈의 최상위 탐색
탐색 구성요소에는 NavigationUI
클래스가 포함되어 있습니다.
이 클래스에는 상단 앱 바, 탐색 창 및 하단 탐색으로 탐색을 관리하는 정적 메서드가 포함되어 있습니다. 앱의 최상위 대상이 기능 모듈에서 제공하는 UI 요소로 구성되어 있다면 app
모듈이 최상위 탐색 및 UI 요소를 배치하기에 적합한 위치입니다. 앱 모듈은 공동작업 기능 모듈에 종속되므로 앱 모듈 내에 정의된 코드에서 모든 대상에 액세스할 수 있습니다. 즉, 항목 ID가 대상 ID와 일치하면 NavigationUI
를 사용하여 대상을 메뉴 항목에 연결할 수 있습니다.
그림 2에서 예로 든 app
모듈은 기본 활동에서 BottomNavigationView
를 정의합니다. 메뉴의 메뉴 항목 ID는 라이브러리 그래프의 탐색 그래프 ID와 일치합니다.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@id/home_nav_graph"
android:icon="@drawable/ic_home"
android:title="Home"
app:showAsAction="ifRoom"/>
<item
android:id="@id/favorites_nav_graph"
android:icon="@drawable/ic_favorite"
android:title="Favorites"
app:showAsAction="ifRoom"/>
<item
android:id="@id/settings_nav_graph"
android:icon="@drawable/ic_settings"
android:title="Settings"
app:showAsAction="ifRoom" />
</menu>
NavigationUI
가 하단 탐색을 처리하도록 하려면 다음 예와 같이 기본 활동 클래스의 onCreate()
에서 setupWithNavController()
를 호출합니다.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment val navController = navHostFragment.navController findViewById<BottomNavigationView>(R.id.bottom_nav) .setupWithNavController(navController) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); NavHostFragment navHostFragment = (NavHostFragment) supportFragmentManager.findFragmentById(R.id.nav_host_fragment); NavController navController = navHostFragment.getNavController(); BottomNavigationView bottomNav = findViewById(R.id.bottom_nav); NavigationUI.setupWithNavController(bottomNav, navController); }
이 코드를 사용하면 NavigationUI
는 사용자가 하단 탐색 항목을 클릭할 때 적절한 라이브러리 그래프로 이동합니다.
일반적으로 앱 모듈이 기능 모듈의 탐색 그래프 내에 깊이 삽입된 특정 대상에 심하게 종속되는 것은 좋지 않습니다. 대부분의 경우 개발자는 삽입 또는 포함된 탐색 그래프의 진입점에 대해서만 앱 모듈이 알기를 바랍니다. 이는 기능 모듈 외에도 적용됩니다. 라이브러리의 탐색 그래프 내에 깊이 있는 대상에 연결해야 한다면 딥 링크를 사용하는 것이 좋습니다. 딥 링크는 라이브러리가 다른 라이브러리의 탐색 그래프에 있는 대상으로 이동하는 유일한 방법이기도 합니다.
기능 모듈 탐색
컴파일 시 독립된 기능 모듈은 서로 확인할 수 없으므로 ID를 사용하여 다른 모듈의 대상으로 이동할 수 없습니다. 대신 딥 링크를 사용하여 암시적 딥 링크와 연결된 대상으로 직접 이동합니다.
이전 예를 계속 사용하면서 :feature:home
모듈의 버튼에서 :feature:settings
모듈에 중첩된 대상으로 이동해야 한다고 가정해보겠습니다. 다음과 같이 설정 탐색 그래프에서 대상에 딥 링크를 추가하면 됩니다.
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/settings_nav_graph"
app:startDestination="@id/settings_fragment_one">
...
<fragment
android:id="@+id/settings_fragment_two"
android:name="com.example.google.login.SettingsFragmentTwo"
android:label="@string/settings_fragment_two" >
<deepLink
app:uri="android-app://example.google.app/settings_fragment_two" />
</fragment>
</navigation>
그런 다음 홈 프래그먼트에서 버튼의 onClickListener
에 다음 코드를 추가합니다.
Kotlin
button.setOnClickListener { val request = NavDeepLinkRequest.Builder .fromUri("android-app://example.google.app/settings_fragment_two".toUri()) .build() findNavController().navigate(request) }
Java
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { NavDeepLinkRequest request = NavDeepLinkRequest.Builder .fromUri(Uri.parse("android-app://example.google.app/settings_fragment_two")) .build(); NavHostFragment.findNavController(this).navigate(request); } });
작업 또는 대상 ID를 사용하는 탐색과 달리 모든 그래프의 어떤 URI로도 이동할 수 있고 모듈 간에도 이동할 수 있습니다.
URI를 사용하여 이동할 때 백 스택은 재설정되지 않습니다. 이 동작은 이동 중 백 스택이 교체되는 명시적 딥 링크 탐색과는 다릅니다.