내비게이션 해달래요.

안드로이드 엔지니어로서, 당신들 중 많은 사람들이 이미 다중 모듈 프로젝트의 개발에 접근했을 것입니다. 만약 그렇지 않다면, 이렇게 하는 것을 고려해 주십시오. 아마도 Joe Birch의 이 멋진 글을 볼 수 있을 것입니다.


만약 이 주제에 대해 경험이 있다면, 다중 모듈 프로젝트에서 가장 도전적인 문제 중 하나가 서로 다른 기능 모듈 사이를 어떻게 내비게이션하는지 알 수 있습니다.
이 주제를 둘러싸고 가능한 방법들이 많은데, 구글 내비게이션 구성 요소를 기반으로 하는 방법에 대해 토론하겠습니다.
만약 당신에게 이런 상황이 있다면:
하나의 응용 프로그램 모듈과 몇 개의 기타 기능 모듈

이제 우리가 feature 1->feature 2에서 내비게이션을 원한다고 가정해 봅시다.
당신이 하고 싶은 첫 번째는Gradle fromfeature 1->feature 2에 당신이 원하는 목적지를 볼 수 있도록 새로운 의존항을 도입하는 것입니다.
알겠습니다. 이것은 좋은 실천이 아닙니다. 잠시 후에 발생할 수 있기 때문에 feature 1 <-feature 2에서 돌아와야 합니다. 그리고 이 새로운 의존항을 도입하면 프로젝트에 순환 의존항이 있을 것입니다.

우리가 왜 서로 다른 모듈 사이에서 내비게이션이 이렇게 복잡한지 이해한 이상 우리는 내비게이션 구성 요소의 도움으로 이 문제를 해결하는 좋은 방법을 찾을 수 있다.
이 글에서, 나는 당신이 적어도 네비게이션 구성 요소가 무엇인지, 무엇을 할 수 있는지에 대해 기본적으로 알고 있다고 가정할 것이다.
가능한 한 간단하게 설명하기 위해서, 우리는 네비게이션 구성 요소가 도구라고 말할 수 있다. 네비게이션 구성 요소는 destinations 라는 이름의 routes 에서 모든 XMLNavigation Graph 를 설명하고, 고급 API를 제공하여 네비게이션을 할 수 있다.
이 예에서 하나의 기능은 우리에게 큰 도움이 된다. 하나의 단일 네비게이션 그림의 내용을 여러 개로 나눌 수 있다는 것이다.
이제 이러한 개념들을 살펴보고 탐색을 통해 달성하고자 하는 모든 목표를 요약해 보겠습니다.
  • 모든 기능은 자신의 도형에 대해 책임을 져야 한다.
  • 모든 기능은 응용 프로그램 내에서 사용할 수 있는 모든 목적지에 도달할 수 있어야 한다.
  • 순환 의존을 피한다.
  • 좋아!이제 드디어 인코딩할 때가 됐어요!

    우리가 해야 할 첫 번째 일은 모든 특성에 대해 Navigation Graphs를 성명하는 것이다. 따라서 우리는 다음과 같은 상황에서 끝낼 것이다.

    이렇게 하면 main_graph.xml에서 다음 작업을 수행할 수 있습니다.
    <include app:graph="@navigation/feature_1_graph.xml" />
    
    <include app:graph="@navigation/feature_2_graph.xml" />
    
    <include app:graph="@navigation/feature_3_graph.xml" />
    
    이렇게 하면 각 기능은 자신의 내부Navigation Graph를 책임지고 이 기능에 필요한 입구점만 공개해야 한다.
    그리고 응용 프로그램은 모든 sub-graphs를 수집하여 main_graph에 포함시켜 모든 기능이 내비게이션을 실행할 수 있도록 한다.
    현재 우리는 단지 다른 문제만 있다. 어떻게 내비게이션을 집행합니까?
    탐색 구성 요소를 사용하여 탐색하려면 다음 두 가지가 필요합니다.
  • 우리가 도착하고자 하는 목적지는 main_graph.xml에 포함되어 있다.
  • 대상 입구점의 ID입니다.
  • 첫 번째는 이미 완성되었기 때문에 우리는 두 번째에 주목해야 한다.
    이 문제를 해결하려면 다음과 같은 팁을 사용할 수 있습니다.
    공유 위치의 모든 포털 ID를 미리 선언합니다.destinations.xml
    <resources>
    
        <!--
        This resource file is the place where you should declare public navigable destinations inside the app
        -->
    
        <item name="feature1Fragment" type="id" />
        <item name="feature2Fragment" type="id" />
        <item name="feature3Fragment" type="id" />
    
    </resources>
    
    이러한 방법으로 우리는 사전에 성명된 ID를 사용하여 나중에 목적지 ID를 제공하거나 목적지 ID를 사용하는 새로운 루트를 실현할 수 있다.feature_1_graph.xml
    <navigation xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/feature_1_graph"
        app:startDestination="@id/feature1Fragment">
    
        <fragment
            android:id="@id/feature1Fragment"
            android:name="com.navigation.sample.feature1.Feature1Fragment"
            android:label="Feature1Fragment">
    
            <action
                android:id="@+id/feature1ToFeature2"
                app:destination="@id/feature2Fragment" />
    
        </fragment>
    
    </navigation>
    
    이때Gradle 의존 관계도는 다음과 같아야 한다.

    이제 목표 목록을 살펴보고 지금까지 우리가 얼마나 많은 진전을 거두었는지 살펴보자.

  • 모든 기능은 자신의 도형에 대해 책임을 져야 한다.✅

  • 모든 기능은 응용 프로그램 내의 모든 사용 가능한 목적지에 도달할 수 있어야 한다.✅

  • 순환 의존을 피하다.✅
  • 목표 목록에서 보듯이, 우리가 실현한 해결 방안은 우리가 정한 모든 수요를 충족시켰지만, 우리는 여전히 마음대로 개선할 수 있는 것이 하나 있습니다.
    이 솔루션에는 다음과 같은 요구 사항이 있습니다.
    매번 우리가 기능을 추가하거나 삭제하려고 할 때, 우리는 반드시 수동으로 main_graph.xmldestinations.xml 를 수정하여 포함된 기능을 정확하게 업데이트해야 한다.
    이것은 결국 큰 문제가 아니지만, 개발자가 매우 게으르기 때문에, 우리는 이 문제를 위해 더 좋은 해결 방안을 찾으려고 시도할 수 있다.😝
    그런데 저희가 뭘 할 수 있을까요?🤔
    이 아이디어는 모든 sub-graphs 인용을 수집하고 실행할 때 프로그래밍 방식으로 main_graph.xml 에 포함시키는 것입니다.
    이 결과에 도달하기 위해서 우리는 Dependency Injection를 사용할 것이다.
    네가 Dagger2를 좋아하든 Koin을 좋아하든 다른 것을 좋아하든 상관없다.
    중요한 것은 모든 기능에서 이 기능의 내비게이션 인용을 자체 모듈 외에 공개할 수 있어야 한다는 것이다.
    간단한 예를 살펴보겠습니다.
    @Module
    object Feature1GraphModule {
    
        @Provides
        @IntoSet
        fun provideGraphReference() = R.navigation.feature_1_graph
    }
    
    그런 다음 모든 그래픽 참조에 액세스하여 다음 코드를 사용하여 main_graph에 포함할 수 있어야 합니다.
    val mainGraph = navController.navInflater.inflate(R.navigation.main_graph)
    
    // subGraphsIDs is the set of all the sub-graphs collected by Dagger multi-binding
    
    subGraphsIDs
       .map { graphId ->
          navController.navInflater.inflate(graphId)
       }
       .forEach { graph->
          mainGraph.addAll(graph)
       }
    
    navController.graph = mainGraph
    
    이 작업은 전체 애플리케이션에서 볼 수 있도록 운영 애플리케이션NavController에서 수행해야 합니다.
    이제 Gradle 의존 관계도를 마지막으로 살펴보겠습니다.

    보시다시피 지금 우리는 새로운 모듈sub-graphs이 있습니다.
    이것은 main_activity_feature/MainActivity의 위치입니다.
    이 모듈에서는 제가 설명한 설정을 실행해야 합니다.
    또 다른 작은 차이점은 현재Main NavController 모듈이 app, 내비게이션 또는 기타 어떤 정보도 모른다는 것이다.
    현재main_graph 모듈은 기능 모듈에만 의존하여 모든 것을 수집한다app. 이것은 코드 유지보수에 있어 매우 큰 장점이다. 왜냐하면 이런 방식을 통해 매번 기능을 추가하거나 삭제할 때마다 정확한 DI 설정만 제공하면 완성되기 때문이다!

    이런 탐색 방법의 작업 예는 나의 개인 항목에서 찾을 수 있다.

    해리프비렌티 호텔 / TimeToPlay



    나는 네가 이 작은 댓글을 좋아하길 바란다. 네가 여기까지 읽어줘서 고마워.

    좋은 웹페이지 즐겨찾기