탐색 코드 모듈화

이 페이지는 탐색 코드를 모듈화하기 위한 가이드입니다. 이 가이드는 일반적인 앱 모듈화 가이드를 보완하기 위한 것입니다.

개요

탐색 코드 모듈화는 관련 탐색 키와 해당 키가 나타내는 콘텐츠를 개별 모듈로 분리하는 프로세스입니다. 이렇게 하면 책임이 명확하게 분리되고 앱의 여러 기능 간에 이동할 수 있습니다.

탐색 코드를 모듈화하려면 다음 단계를 따르세요.

  • 앱의 각 기능에 대해 apiimpl 하위 모듈을 만듭니다.
  • 각 기능의 탐색 키를 해당 api 모듈에 배치
  • 각 기능의 entryProviders 및 탐색 가능한 콘텐츠를 연결된 impl 모듈에 배치합니다.
  • 종속 항목 삽입을 사용하거나 직접 기본 앱 모듈에 entryProviders 제공

기능을 API 및 구현 하위 모듈로 분리

앱의 각 기능에 대해 apiimpl('구현'의 약자)이라는 두 개의 하위 모듈을 만듭니다. 다음 표를 사용하여 탐색 코드를 배치할 위치를 결정하세요.

모듈 이름

포함

api

탐색 키

impl

NavEntryentryProvider 정의를 비롯한 해당 기능의 콘텐츠 콘텐츠로 키 확인도 참고하세요.

이 접근 방식을 사용하면 impl 모듈에 포함된 콘텐츠가 해당 모듈의 api 모듈에 포함된 다른 모듈의 탐색 키에 종속되도록 허용하여 한 기능이 다른 기능으로 이동할 수 있습니다.

`impl` 모듈이 `api` 모듈에 종속될 수 있는 방법을 보여주는 기능 모듈 종속 항목 다이어그램
그림 1. 구현 모듈이 API 모듈에 종속될 수 있는 방법을 보여주는 기능 모듈 종속 항목 다이어그램

확장 함수를 사용하여 탐색 항목 분리

Navigation 3에서는 탐색 가능한 콘텐츠가 탐색 항목을 사용하여 정의됩니다. 이러한 항목을 별도의 모듈로 분리하려면 EntryProviderScope에서 확장 함수를 만들고 해당 기능의 impl 모듈로 이동합니다. 이를 항목 빌더라고 합니다.

다음 코드 예는 탐색 항목 두 개를 빌드하는 항목 빌더를 보여줍니다.

// import androidx.navigation3.runtime.EntryProviderScope
// import androidx.navigation3.runtime.NavKey

fun EntryProviderScope<NavKey>.featureAEntryBuilder() {
    entry<KeyA> {
        ContentRed("Screen A") {
            // Content for screen A
        }
    }
    entry<KeyA2> {
        ContentGreen("Screen A2") {
            // Content for screen A2
        }
    }
}

기본 앱 모듈에서 entryProvider를 정의할 때 entryProvider DSL을 사용하여 해당 함수를 호출합니다.

// import androidx.navigation3.runtime.entryProvider
// import androidx.navigation3.ui.NavDisplay
NavDisplay(
    entryProvider = entryProvider {
        featureAEntryBuilder()
    },
    // ...
)

종속성 주입을 사용하여 기본 앱에 항목 추가

위 코드 예시에서 각 항목 빌더는 entryProvider DSL을 사용하여 기본 앱에서 직접 호출됩니다. 앱에 화면이나 기능 모듈이 많은 경우 이 방법이 적합하지 않을 수 있습니다.

이 문제를 해결하려면 각 기능 모듈이 종속 항목 삽입을 사용하여 앱의 활동에 항목 빌더를 제공하도록 합니다.

예를 들어 다음 코드는 Dagger 멀티바인딩, 특히 @IntoSet를 사용하여 항목 빌더를 MainActivity가 소유한 Set에 삽입합니다. 그런 다음 entryProvider 내에서 반복적으로 호출되므로 여러 항목 빌더 함수를 명시적으로 호출할 필요가 없습니다.

기능 모듈

// import dagger.Module
// import dagger.Provides
// import dagger.hilt.InstallIn
// import dagger.hilt.android.components.ActivityRetainedComponent
// import dagger.multibindings.IntoSet

@Module
@InstallIn(ActivityRetainedComponent::class)
object FeatureAModule {

    @IntoSet
    @Provides
    fun provideFeatureAEntryBuilder() : EntryProviderScope<NavKey>.() -> Unit = {
        featureAEntryBuilder()
    }
}

앱 모듈

// import android.os.Bundle
// import androidx.activity.ComponentActivity
// import androidx.activity.compose.setContent
// import androidx.navigation3.runtime.EntryProviderScope
// import androidx.navigation3.runtime.NavKey
// import androidx.navigation3.runtime.entryProvider
// import androidx.navigation3.ui.NavDisplay
// import javax.inject.Inject

class MainActivity : ComponentActivity() {

    @Inject
    lateinit var entryBuilders: Set<@JvmSuppressWildcards EntryProviderScope<NavKey>.() -> Unit>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NavDisplay(
                entryProvider = entryProvider {
                    entryBuilders.forEach { builder -> this.builder() }
                },
                // ...
            )
        }
    }
}

탐색 항목이 탐색해야 하는 경우(예: 새 화면으로 이동하는 UI 요소가 포함된 경우) 앱의 탐색 상태를 수정할 수 있는 객체를 각 빌더 함수에 삽입합니다.

리소스

Navigation 3 코드를 모듈화하는 방법을 보여주는 코드 샘플은 다음을 참고하세요.