Özellik modülleriyle gezinme

Dynamic Navigator kitaplığı, tarayıcının Hedeflerle çalışmak için Jetpack Navigasyon bileşeni olarak tanımlanan özellik modüllerini inceleyin. Bu kitaplık, isteğe bağlı özelliklerin sorunsuz şekilde yüklenmesini de sağlar. modüllerini tanıtacağım.

Kurulum

Özellik modüllerini desteklemek için uygulama modülünüzün build.gradle dosyasında aşağıdaki bağımlılıkları kullanın:

Eski

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")
}

Diğer Gezinme bağımlılıklarının api yapılandırmalarını kullanması gerektiğini unutmayın kullanılabilir hale getirebilirsiniz.

Temel kullanım

Özellik modüllerini desteklemek için önce tüm Uygulamanızda 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"
    ... />

Daha sonra <activity>, <fragment> veyaapp:moduleName com.android.dynamic-feature modülünüzde <navigation> hedef DynamicNavHostFragment ile ilişkilendirilen gezinme grafikleri. Bu özellik, Dynamic Navigator kitaplığına hedefin sizin belirttiğiniz ada sahip bir özellik modülüne aittir.

<fragment
    app:moduleName="myDynamicFeature"
    android:id="@+id/featureFragment"
    android:name="com.google.android.samples.feature.FeatureFragment"
    ... />

Bu hedeflerden birine gittiğinizde Dynamic Navigator kitaplığı özellik modülünün yüklü olup olmadığını kontrol eder. Özellik modülü zaten mevcutsa uygulamanız hedefe beklendiği gibi gider. Modül mevcut değilse uygulamanızda bir ara ilerleme parçası gösterilir hedefi belirler. ilerleme parçası, ilerleme çubuğunun yer aldığı bir kullanıcı arayüzünü gösterir ve emin olun.

gezinirken ilerleme çubuğu gösteren kullanıcı arayüzünü gösteren iki yükleme ekranı
         bir özellik modülüne ilk kez
Şekil 1. Kullanıcı gezinirken ilerleme çubuğunu gösteren kullanıcı arayüzü isteğe bağlı bir özellik olarak ilk kez kullanıma sunulacak. Uygulamada bu ekran şu şekilde görünür: indirin.

Bu kullanıcı arayüzünü özelleştirmek veya yüklemeyi manuel olarak gerçekleştirmek için ilerleme durumunu görmek için İlerleme parçasını özelleştirin ve Bu konunun istek durumu bölümlerini izleyin.

app:moduleName belirtilmeyen hedefler olmadan çalışmaya devam eder ve uygulamanız normal bir NavHostFragment kullanıyormuş gibi davranır.

İlerleme parçasını özelleştir

Her gezinme grafiğinde ilerleme parçası uygulamasını geçersiz kılabilirsiniz. app:progressDestination özelliğini hedefin kimliğine ayarlayarak onay kutusunu işaretleyin. Özel ilerleme durumunuz Hedef şöyle olmalıdır: Fragment, şununla türetilir: AbstractProgressFragment. Yüklemeyle ilgili bildirimler için soyut yöntemleri geçersiz kılmanız gerekir ve diğer etkinlikleri görebilirsiniz. Ardından, yükleme işleminin ilerleme durumunu Tercih ettiğiniz kullanıcı arayüzü.

Varsayılan uygulamanın DefaultProgressFragment sınıfı, yükleme durumunu göstermek için bu API'yi kullanır.

İstek durumunu izleme

Dynamic Navigator kitaplığı, aşağıdakine benzer bir kullanıcı deneyimi akışı uygulamanızı bir inç İsteğe bağlı teslimat için kullanıcı deneyimi en iyi uygulamaları, Kullanıcının bir sonraki ekran bağlamındaki yüklemeniz gerekir. Bu, bir arabulucu kullanımı için orta kullanıcı arayüzü veya ilerleme parçası.

belirten bir simge içeren alt gezinme çubuğunu gösteren ekran
         bir özellik modülünün indirildiği
Şekil 2. Şuradan indirme işleminin ilerleme durumunu gösteren ekran: gezinme çubuğunu kullanın.

Bu senaryoda, proje yöneticisi olarak tüm yükleme durumlarını, ilerleme değişikliklerini, hataları ve bu şekilde devam eder.

Bu engellemeyen gezinme akışını başlatmak için DynamicExtras şunu içeren nesne DynamicInstallMonitor - NavController.navigate(), aşağıdaki örnekte gösterildiği gibi:

Kotlin

val navController = ...
val installMonitor = DynamicInstallMonitor()

navController.navigate(
    destinationId,
    null,
    null,
    DynamicExtras(installMonitor)
)

Java

NavController navController = ...
DynamicInstallMonitor installMonitor = new DynamicInstallMonitor();

navController.navigate(
    destinationId,
    null,
    null,
    new DynamicExtras(installMonitor);
)

navigate() çağrısından hemen sonra gezinme girişiminin sonuçlanıp sonuçlanmadığını görmek için installMonitor.isInstallRequired bir özellik modülü kurulumu olabilir.

  • Değer false ise normal bir hedefe gidiyorsunuz ve gitmiyorsunuz başka bir şey yapmaları gerekmez.
  • Değer true ise şuna sahip LiveData nesnesini gözlemlemeye başlamanız gerekir: şu anda installMonitor.status konumunda. Bu LiveData nesne yayıyor SplitInstallSessionState en son güncellemeleri ve güncellemeleri almak için bu videoları izleyin. Bu güncellemeler yükleme bilgilerini içerir ilerleme etkinliklerini görebilirsiniz. Tümünü işlemeyi unutmayın ilgili durumlar için Play Temel Kılavuzu, dahil kullanıcıdan onay isteme bakın.

    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);
              }
          }
      });
    }
    

    Java

    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);
              }
          }
      });
    }
    

Yükleme tamamlandığında LiveData nesnesi bir SplitInstallSessionStatus.INSTALLED durumu. Ardından NavController.navigate() tekrar. Modül yüklenmiş olduğundan Uygulama başarılı olur ve uygulama hedefe beklendiği gibi gider.

Yüklemenin tamamlanması veya yüklemenin tamamlanması gibi bir terminal durumuna ulaştıktan sonra yükleme başarısız olursa bellekten kaçınmak için LiveData gözlemleyicinizi kaldırmalısınız. sızdır. Durumun bir terminal durumunu temsil edip etmediğini kontrol etmek için SplitInstallSessionStatus.hasTerminalStatus()

Bkz. AbstractProgressFragment bu gözlemcinin örnek bir uygulamasını görebilirsiniz.

Dahil edilen grafikler

Dynamic Navigator kitaplığı, şurada tanımlanan grafikleri dahil etmeyi destekler: özellik modüllerinden yararlanın. Bir özellikte tanımlanmış bir grafiği dahil etmek için modülünü kullanarak şunları yapın:

  1. Aşağıdaki gibi, <include/> yerine <include-dynamic/> kullanın örnek:

    <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" />
    
  2. <include-dynamic ... /> içinde şu özellikleri belirtmeniz gerekir:

    • app:graphResName: Gezinme grafiği kaynak dosyasının adı. İlgili içeriği oluşturmak için kullanılan adı grafiğin dosya adından türetilir. Örneğin, grafik res/navigation/nav_graph.xml, kaynak adı: nav_graph.
    • android:id - grafik hedef kimliği. Dynamic Navigator kitaplığı kök öğesinde bulunan android:id değerlerini yok sayar: dahil edilir.
    • app:moduleName: modülün paket adı.

Doğru schemaPackage'ı kullanın

app:graphPackage değerinin Navigasyon olarak doğru olması önemlidir. bileşeni, özellikte belirtilen navGraph parametresini içeremez modülünü kullanabilirsiniz.

Bir dinamik özellik modülünün paket adı, modülün adını temel uygulama modülünün applicationId öğesine ekleyin. Dolayısıyla temel uygulama modülünün applicationId değeri com.example.dynamicfeatureapp ve dinamik özellik modülünün adı DynamicFeatureModule, ardından paket dinamik modülün adı şudur: com.example.dynamicfeatureapp.DynamicFeatureModule. Bu paket adı: büyük/küçük harfe duyarlıdır.

Herhangi bir şüpheniz varsa özellik modülünün paket adını onaylayabilirsiniz oluşturulan AndroidManifest.xml kontrol edilir. Projeyi oluşturduktan sonra alıcı: <DynamicFeatureModule>/build/intermediates/merged_manifest/debug/AndroidManifest.xml, Bu kod aşağıdaki gibi görünecektir:

<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 değeri, dinamik özellik modülünün adıyla, paket ise temel uygulama modülünün applicationId değeriyle eşleşmelidir. app:graphPackage, bunların kombinasyonudur: com.example.dynamicfeatureapp.DynamicFeatureModule.

Yalnızca startDestination içine gidebilirsiniz. include-dynamic gezinme grafiği. Dinamik modül, kendiliğinden ve temel uygulamanın bundan haberi yoktur.

"include-dynamic" mekanizması, temel uygulama modülünün iç içe yerleştirilmiş gezinme grafiği bir örneğidir. İç içe yerleştirilmiş gezinme grafiği, gibi gezinme grafikleri de oluşturabilir. Kök gezinme grafiği (yani, olabilir), iç içe yerleştirilmiş gezinme grafiğinin kendisini yalnızca bir alt öğeleri değil, hedef olacaktır. Dolayısıyla startDestination, dahil etme-dinamik gezinme grafiği hedeftir.

Sınırlamalar

  • Dinamik olarak eklenmiş grafikler şu anda derin bağlantıları desteklememektedir.
  • Dinamik olarak yüklenmiş iç içe yerleştirilmiş grafikler (yani, bir <navigation> öğesi için app:moduleName) şu anda derin bağlantıları desteklememektedir.