Çok modüllü projeler için gezinmeyle ilgili en iyi uygulamalar

Gezinme grafiği, aşağıdakilerin herhangi bir kombinasyonundan oluşabilir:

  • <fragment> hedefi gibi tek bir hedef.
  • Bir dizi ilgili hedefi içeren iç içe yerleştirilmiş bir grafik.
  • Başka bir gezinme grafiği dosyasını iç içe yerleştirilmiş gibi yerleştirmenize olanak tanıyan bir <include> öğesi.

Bu esneklik, daha küçük gezinme grafikleri ayrı modüller tarafından sağlansa bile, uygulamanızın tam gezinme grafiğini oluşturmak için küçük gezinme grafiklerini birleştirmenize olanak tanır.

Bu konudaki örneklerde, her özellik modülü tek bir özelliğe odaklanmıştır ve bu özelliğin uygulanması için gereken tüm hedefleri içeren tek bir gezinme grafiği sunar. Bir üretim uygulamasında, daha düşük düzeyde, bu üst düzey özellik modülünün uygulama ayrıntıları olan birçok alt modülünüz olabilir. Bu özellik modüllerinin her biri, doğrudan veya dolaylı olarak app modülünize dahil edilir. Bu dokümanda kullanılan çok modüllü uygulama örneği aşağıdaki yapıya sahiptir:

örnek bir çok modüllü uygulamanın bağımlılık grafiği
örnek uygulamanın başlangıç hedefi
Şekil 1. Örnek uygulama için uygulama mimarisi ve başlangıç hedefi.

Her özellik modülü, kendi gezinme grafiği ve hedefleri olan bağımsız bir birimdir. app modülü her bir modüle bağlıdır ve aşağıdaki gibi build.gradle dosyasında uygulama ayrıntıları olarak eklenir:

Modern

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 modülünün rolü

app modülü, uygulamanız için tam grafiği sağlamaktan ve kullanıcı arayüzünüze NavHost eklemekten sorumludur. app modülünün gezinme grafiğinde, <include> kullanarak kitaplık grafiklerine başvurabilirsiniz. <include> kullanımı, iç içe yerleştirilmiş bir grafik kullanmayla işlevsel olarak aynı olsa da <include>, aşağıdaki örnekte gösterildiği gibi diğer proje modüllerindeki veya kitaplık projelerindeki grafikleri destekler:

<?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>

Bir kitaplık üst düzey gezinme grafiğine dahil edildikten sonra, kitaplık grafiklerine gerektiği şekilde gidebilirsiniz. Örneğin, aşağıda gösterildiği gibi, gezinme grafiğinizdeki bir bölümden ayarlar grafiğine gitmek için bir işlem oluşturabilirsiniz:

<?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>

Birden fazla özellik modülünün giriş grafiği gibi ortak bir hedef grubuna referans vermesi gerektiğinde, her bir özellik modülünün gezinme grafiğine bu ortak hedefleri eklememeniz gerekir. Bunun yerine, bu yaygın hedefleri app modülünüzün gezinme grafiğine ekleyin. Daha sonra her özellik modülü, bu ortak hedeflere gitmek için özellik modülleri arasında gezinebilir.

Önceki örnekte, işlem @id/settings_nav_graph gezinme hedefini belirtir. Bu kimlik, dahil edilen @navigation/settings_navigation. grafiğinde tanımlanan bir hedefi ifade eder

Uygulama modülünde üst düzey gezinme

Gezinme bileşeni bir NavigationUI sınıfı içerir. Bu sınıf; üst uygulama çubuğu, gezinme çekmecesi ve alt gezinmeyle gezinmeyi yöneten statik yöntemler içerir. Uygulamanızın üst düzey hedefleri, özellik modülleri tarafından sağlanan kullanıcı arayüzü öğelerinden oluşuyorsa app modülü, üst düzey gezinme ve kullanıcı arayüzü öğelerinin yerleştirilebileceği doğal bir yerdir. Uygulama modülü, ortak çalışan özellik modüllerine bağlı olduğundan, bu modüllerin tüm hedeflerine uygulama modülünüzde tanımlanan koddan erişilebilir. Yani, öğenin kimliği bir hedefin kimliğiyle eşleşiyorsa hedefleri menü öğelerine bağlamak için NavigationUI kullanabilirsiniz.

Şekil 2'de, örnek app modülünde ana etkinliğinde bir BottomNavigationView tanımlanmıştır. Menüdeki menü öğesi kimlikleri, kitaplık grafiklerinin gezinme grafiği kimlikleriyle eşleşir:

<?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 uygulamasının alt gezinmeyi işlemesine izin vermek için aşağıdaki örnekte gösterildiği gibi, ana etkinlik sınıfınızdaki onCreate() adlı operatörden setupWithNavController() yöntemini çağırın:

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

Bu kodu uyguladığınızda, kullanıcı alttaki gezinme öğelerinden birini tıkladığında NavigationUI uygun kitaplık grafiğine gider.

Uygulama modülünüzün, özellik modüllerinizin gezinme grafiğine derin bir düzeyde yerleştirilmiş belirli bir hedefe bağımlılığının genellikle kötü bir uygulama olduğunu unutmayın. Çoğu durumda, uygulama modülünüzün yalnızca yerleştirilmiş veya dahil edilen gezinme grafiklerine giriş noktası hakkında bilgi sahibi olmasını istersiniz (bu, özellik modüllerinin dışında da geçerlidir). Kitaplığınızın gezinme grafiğinin derinlerinde yer alan bir hedefe bağlantı oluşturmanız gerekiyorsa bunu yapmanın tercih edilen yolu derin bağlantı kullanmaktır. Derin bağlantı, bir kitaplığın başka bir kitaplığın gezinme grafiğindeki bir hedefe gitmesinin tek yoludur.

Özellik modülleri arasında gezinme

Derleme sırasında bağımsız özellik modülleri birbirini göremez. Bu nedenle kimlikleri diğer modüllerdeki hedeflere gitmek için kullanamazsınız. Bunun yerine, doğrudan dolaylı bir derin bağlantı ile ilişkilendirilmiş hedefe gitmek için derin bağlantı kullanın.

Önceki örnekten devam edersek, :feature:home modülündeki bir düğmeden :feature:settings modülünde iç içe yerleştirilmiş bir hedefe gitmeniz gerektiğini varsayalım. Bunu, aşağıda gösterildiği gibi ayarlar gezinme grafiğinde hedefe bir derin bağlantı ekleyerek yapabilirsiniz:

<?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>

Ardından, ana sayfa parçasındaki düğmenin onClickListener öğesine aşağıdaki kodu ekleyin:

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

İşlem veya hedef kimliklerini kullanarak gezinmenin aksine, modüller arasında bile olsa herhangi bir grafikteki herhangi bir URI'ye gidebilirsiniz.

URI kullanılarak gezinirken, arka yığın sıfırlanmaz. Bu davranış, gezinme sırasında geri yığınının değiştirildiği açık derin bağlantı gezinmesinden farklıdır.