Hedefler arasında veri geçirme

Navigasyon, bir hedef için bağımsız değişkenler tanımlayarak verileri bir gezinme işlemine eklemenize olanak tanır. Örneğin, bir kullanıcı profili hedefi, hangi kullanıcının gösterileceğini belirlemek için bir kullanıcı kimliği bağımsız değişkeni alabilir.

Genel olarak, hedefler arasında yalnızca minimum miktarda veri iletmeyi tercih etmeniz önerilir. Örneğin, Android'de tüm kayıtlı durumların toplam alanı sınırlı olduğundan, bir nesneyi almak için nesnenin kendisini iletmek yerine bir anahtar iletmeniz gerekir. Büyük miktarda veri iletmeniz gerekiyorsa ViewModel'e genel bakış bölümünde açıklandığı gibi bir ViewModel kullanın.

Hedef bağımsız değişkenlerini tanımlama

Hedefler arasında veri aktarmak için önce bağımsız değişkeni, aşağıdaki adımları uygulayarak alan adı alan hedefe ekleyerek tanımlayın:

  1. Gezinme Düzenleyici'de bağımsız değişkeni alan hedefi tıklayın.
  2. Özellikler panelinde Ekle'yi (+) tıklayın.
  3. Görünen Bağımsız Değişken Bağlantısı Ekle penceresine bağımsız değişken adını, bağımsız değişken türünü, bağımsız değişkenin boş olup olmadığını ve gerekirse varsayılan değeri girin.
  4. Ekle'yi tıklayın. Parametrenin artık Özellikler panelindeki Parametreler listesinde göründüğünü fark edin.
  5. Ardından, sizi bu hedefe götüren ilgili işlemi tıklayın. Özellikler panelinde, yeni eklenen bağımsız değişkeninizi Bağımsız Değişken Varsayılan Değerleri bölümünde görebilirsiniz.
  6. Ayrıca bağımsız değişkenin XML'e eklendiğini de görebilirsiniz. XML görünümüne geçmek için Metin sekmesini tıklayın ve bağımsız değişkeninizin, bağımsız değişkeni alan hedefe eklendiğini fark edin. Aşağıda bir örnek gösterilmektedir:

     <fragment android:id="@+id/myFragment" >
         <argument
             android:name="myArg"
             app:argType="integer"
             android:defaultValue="0" />
     </fragment>
    

Desteklenen bağımsız değişken türleri

Gezinme kitaplığı aşağıdaki bağımsız değişken türlerini destekler:

Tür app:argType söz dizimi Varsayılan değerler için destek Rotalar tarafından yönetilir Boş değer atanabilir
Tam sayı app:argType="integer" Evet Evet Hayır
Havada Süzülen app:argType="float" Evet Evet Hayır
Uzun app:argType="long" Evet: Varsayılan değerler her zaman "L" son ekiyle bitmelidir (ör. "123L"). Evet Hayır
Boole app:argType="boolean" Evet: "true" veya "false" Evet Hayır
Dize app:argType="string" Evet Evet Evet
Kaynak Referansı app:argType="reference" Evet: Varsayılan değerler "@resourceType/resourceName" (ör. "@style/myCustomStyle") veya "0" biçiminde olmalıdır. Evet Hayır
Özel Paketlenebilir app:argType="<type>". Burada <type>, Parcelable sınıfının tam nitelikli sınıf adıdır. "@null" varsayılan değerini destekler. Diğer varsayılan değerleri desteklemez. Hayır Evet
Özel Serileştirilebilir app:argType="<type>". Burada <type>, Serializable sınıfının tam nitelikli sınıf adıdır. "@null" varsayılan değerini destekler. Diğer varsayılan değerleri desteklemez. Hayır Evet
Özel Enum app:argType="<type>". Burada <type>, enum'un tam nitelikli adıdır. Evet: Varsayılan değerler, tam olmayan adla eşleşmelidir (ör. MyEnum.SUCCESS ile eşleşmek için "SUCCESS"). Hayır Hayır

Bir bağımsız değişken türü boş değerleri destekliyorsa android:defaultValue="@null" kullanarak varsayılan olarak boş bir değer belirtebilirsiniz.

Rotalar, derin bağlantılar ve URI'ler, bağımsız değişkenleriyle birlikte dizelerden ayrıştırılabilir. Bu, önceki tabloda gösterildiği gibi Parcelables ve Serializables gibi özel veri türleri kullanılarak yapılamaz. Özel karmaşık verileri iletmek için verileri ViewModel veya veritabanı gibi başka bir yerde depolayın ve gezinirken yalnızca bir tanımlayıcı iletin. Ardından, gezinme tamamlandıktan sonra verileri yeni konumda alın.

Özel türlerden birini seçtiğinizde Sınıf Seç iletişim kutusu görünür ve bu tür için ilgili sınıfı seçmeniz istenir. Proje sekmesi, mevcut projenizden bir sınıf seçmenize olanak tanır.

Gezinme kitaplığının türü sağlanan değere göre belirlemesi için <inferred type> seçeneğini belirleyebilirsiniz.

Bağımsız değişkenin, seçilen Tür değerinin bir dizisi olması gerektiğini belirtmek için Dizi'yi işaretleyebilirsiniz. Aşağıdakileri göz önünde bulundurun:

  • Liste dizileri ve kaynak referansı dizileri desteklenmez.
  • Diziler, temel türün boş değer desteğinden bağımsız olarak boş değerleri destekler. Örneğin, app:argType="integer[]" kullanıldığında, null bir dizi iletmenin kabul edilebilir olduğunu belirtmek için app:nullable="true" kullanabilirsiniz.
  • Diziler yalnızca tek bir varsayılan değeri destekler: "@null". Diziler başka bir varsayılan değeri desteklemez.

Bir işlemdeki hedef bağımsız değişkenini geçersiz kılma

Hedef düzeyindeki bağımsız değişkenler ve varsayılan değerler, hedefe giden tüm işlemler tarafından kullanılır. Gerekirse işlem düzeyinde bir bağımsız değişken tanımlayarak bağımsız değişkenin varsayılan değerini geçersiz kılabilirsiniz (veya henüz mevcut değilse bir değer ayarlayabilirsiniz). Bu bağımsız değişken, hedefte tanımlanan bağımsız değişkenle aynı ada ve türe sahip olmalıdır.

Aşağıdaki XML, önceki örnekteki hedef düzeyindeki bağımsız değişkeni geçersiz kılan bir bağımsız değişken içeren bir işlem tanımlar:

<action android:id="@+id/startMyFragment"
    app:destination="@+id/myFragment">
    <argument
        android:name="myArg"
        app:argType="integer"
        android:defaultValue="1" />
</action>

Verileri tür güvenliğiyle iletmek için Safe Args'i kullanma

Navigasyon bileşeninde, tür açısından güvenli gezinme ve ilişkili tüm bağımsız değişkenlere erişim için basit nesne ve oluşturucu sınıfları oluşturan Safe Args adlı bir Gradle eklentisi bulunur. Tür güvenliği sağladığı için Safe Args, gezinme ve veri aktarımı için önemle tavsiye edilir.

Gradle kullanmıyorsanız SafeArgs eklentisini kullanamazsınız. Bu gibi durumlarda, verileri doğrudan iletmek için paketleri kullanabilirsiniz.

Projenize Safe Args eklemek için üst düzey build.gradle dosyanıza aşağıdaki classpath öğesini ekleyin:

Groovy

buildscript {
    repositories {
        google()
    }
    dependencies {
        def nav_version = "2.8.4"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

Kotlin

buildscript {
    repositories {
        google()
    }
    dependencies {
        val nav_version = "2.8.4"
        classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version")
    }
}

Ayrıca, mevcut iki eklentiden birini de uygulamanız gerekir.

Java veya karma Java ve Kotlin modüllerine uygun Java dil kodu oluşturmak için bu satırı uygulamanızın veya modülünüzün build.gradle dosyasına ekleyin:

Groovy

plugins {
  id 'androidx.navigation.safeargs'
}

Kotlin

plugins {
    id("androidx.navigation.safeargs")
}

Alternatif olarak, yalnızca Kotlin modüllerine uygun Kotlin kodu oluşturmak için şunları ekleyin:

Groovy

plugins {
  id 'androidx.navigation.safeargs.kotlin'
}

Kotlin

plugins {
    id("androidx.navigation.safeargs.kotlin")
}

AndroidX'e Taşıma bölümünde belirtildiği gibi, gradle.properties dosyanızda android.useAndroidX=true olmalıdır.

Güvenli bağımsız değişkenleri etkinleştirdikten sonra oluşturulan kodunuz, her işlem için ve her gönderen ve alıcı hedef için aşağıdaki türde güvenli sınıflar ve yöntemler içerir.

  • Bir işlemin başladığı her hedef için bir sınıf oluşturulur. Bu sınıfın adı, başlangıç noktasının adına "Yol tarifleri" kelimesinin eklenmesidir. Örneğin, kaynak hedef SpecifyAmountFragment adlı bir parça ise oluşturulan sınıf SpecifyAmountFragmentDirections olarak adlandırılır.

    Bu sınıf, kaynak hedefte tanımlanan her işlem için bir yönteme sahiptir.

  • Argümanını iletmek için kullanılan her işlem için adı işleme dayalı bir iç sınıf oluşturulur. Örneğin, işlem confirmationAction, olarak adlandırılırsa sınıf ConfirmationAction olarak adlandırılır. İşleminiz defaultValue içermeyen bağımsız değişkenler içeriyorsa bağımsız değişkenlerin değerini ayarlamak için ilişkili işlem sınıfını kullanırsınız.

  • Alıcı hedef için bir sınıf oluşturulur. Bu sınıfın adı, hedefin adına "Args" kelimesinin eklenmesidir. Örneğin, hedef parça ConfirmationFragment, olarak adlandırılırsa oluşturulan sınıf ConfirmationFragmentArgs olarak adlandırılır. Parametreleri almak için bu sınıfın fromBundle() yöntemini kullanın.

Aşağıdaki örnekte, bir bağımsız değişken ayarlamak ve bunu navigate() yöntemine iletmek için bu yöntemlerin nasıl kullanılacağı gösterilmektedir:

Kotlin

override fun onClick(v: View) {
   val amountTv: EditText = view!!.findViewById(R.id.editTextAmount)
   val amount = amountTv.text.toString().toInt()
   val action = SpecifyAmountFragmentDirections.confirmationAction(amount)
   v.findNavController().navigate(action)
}

Java

@Override
public void onClick(View view) {
   EditText amountTv = (EditText) getView().findViewById(R.id.editTextAmount);
   int amount = Integer.parseInt(amountTv.getText().toString());
   ConfirmationAction action =
           SpecifyAmountFragmentDirections.confirmationAction();
   action.setAmount(amount);
   Navigation.findNavController(view).navigate(action);
}

Alıcı hedefin kodunda, paketi almak ve içeriğini kullanmak için getArguments() yöntemini kullanın. -ktx bağımlılıkları kullanılırken Kotlin kullanıcıları, bağımsız değişkenlere erişmek için by navArgs() mülk temsilcisini de kullanabilir.

Kotlin

val args: ConfirmationFragmentArgs by navArgs()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val tv: TextView = view.findViewById(R.id.textViewAmount)
    val amount = args.amount
    tv.text = amount.toString()
}

Java

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    TextView tv = view.findViewById(R.id.textViewAmount);
    int amount = ConfirmationFragmentArgs.fromBundle(getArguments()).getAmount();
    tv.setText(amount + "");
}

Safe Args'i genel işlemle kullanma

Güvenli bağımsız değişkenleri global bir işlemle kullanırken aşağıdaki örnekte gösterildiği gibi kök <navigation> öğeniz için bir android:id değeri sağlamanız gerekir:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/main_nav"
            app:startDestination="@id/mainFragment">

    ...

</navigation>

Gezinme, <navigation> öğesi için android:id değerine dayalı bir Directions sınıfı oluşturur. Örneğin, android:id=@+id/main_nav içeren bir <navigation> öğeniz varsa oluşturulan sınıf MainNavDirections olarak adlandırılır. <navigation> öğesindeki tüm hedefler, önceki bölümde açıklanan yöntemlerle ilişkili tüm genel işlemlere erişmek için oluşturulmuş yöntemlere sahiptir.

Paket nesneleriyle hedefler arasında veri geçirme

Gradle kullanmıyorsanız Bundle nesnelerini kullanarak hedefler arasında yine bağımsız değişken iletebilirsiniz. Aşağıdaki örnekte gösterildiği gibi bir Bundle nesnesi oluşturun ve navigate() kullanarak hedefe iletin:

Kotlin

val bundle = bundleOf("amount" to amount)
view.findNavController().navigate(R.id.confirmationAction, bundle)

Java

Bundle bundle = new Bundle();
bundle.putString("amount", amount);
Navigation.findNavController(view).navigate(R.id.confirmationAction, bundle);

Alıcı hedefinizin kodunda, Bundle öğesini almak ve içeriğini kullanmak için getArguments() yöntemini kullanın:

Kotlin

val tv = view.findViewById<TextView>(R.id.textViewAmount)
tv.text = arguments?.getString("amount")

Java

TextView tv = view.findViewById(R.id.textViewAmount);
tv.setText(getArguments().getString("amount"));

Başlangıç hedefine veri aktarma

Uygulamanızın başlangıç hedefine veri iletebilirsiniz. Öncelikle, verileri içeren bir Bundle açıkça oluşturmanız gerekir. Ardından, Bundle değerini başlangıç hedefine iletmek için aşağıdaki yaklaşımlardan birini kullanın:

Başlangıç hedefinizdeki verileri almak için Fragment.getArguments() işlevini çağırın.

ProGuard ile ilgili dikkat edilmesi gereken noktalar

Kodu küçültüyorsanız Parcelable, Serializable ve Enum sınıf adlarınızın, sadeleştirme işlemi kapsamında karartılmasını önlemeniz gerekir. Bunu iki şekilde yapabilirsiniz:

  • @Keep ek açıklamalarını kullanın.
  • Adları koruma kurallarını kullanın.

Aşağıdaki alt bölümlerde bu yaklaşımlar özetlenmiştir.

@Keep ek açıklamalarını kullanma

Aşağıdaki örnekte, model sınıfı tanımlarına @Keep ek açıklamaları eklenmiştir:

Kotlin

@Keep class ParcelableArg : Parcelable { ... }

@Keep class SerializableArg : Serializable { ... }

@Keep enum class EnumArg { ... }

Java

@Keep public class ParcelableArg implements Parcelable { ... }

@Keep public class SerializableArg implements Serializable { ... }

@Keep public enum EnumArg { ... }

Adları koruma kurallarını kullanma

Aşağıdaki örnekte gösterildiği gibi, proguard-rules.pro dosyanıza keepnames kuralları da ekleyebilirsiniz:

proguard-rules.pro

...

-keepnames class com.path.to.your.ParcelableArg
-keepnames class com.path.to.your.SerializableArg
-keepnames class com.path.to.your.EnumArg

...

Ek kaynaklar

Gezinme hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara göz atın.

Codelab uygulamaları

Videolar