Örnek-2: Destination'lar Arasında Veri Aktarma

Bir önceki örneğimizde iki destination arasında geçiş yapmayı öğrendik. Peki bu geçiş sırasında bir veri aktarmak istersek ne yapacağız? Bu dersimizde bunu öğreneceğiz.

Bildiğiniz gibi aslında ulaşmaya çalıştığımız her destination bizim için aynı zamanda basit anlamda bir sayfa anlamında. Navigation komponenti ortaya çıkmadan önce de veri aktarım işlemini Bundle'lar aracılığı ile gerçekleştirebiliyorduk. Artık bu yöntemi klasik metot diye adlandıralım. Navigation'ın getirdiği bir yenilikte veri aktarımını Safe Args ismiyle tip güvenliği sağlayarak yapıyor olması.

Projenizde sayfalar arasında geçiş yaparken tip güvenliği sağlayan Safe Args'ı da kullanacaksanız, ona ait gradle eklemesini de yapmanız gerektiğini ve nasıl yapıldığını 03 numaralı dersimizde öğrenmiştik.

Tip Güvenliği Olmayan Yöntem

Şimdi önceliği klasik metot olan ve tip güvenliği sağlamayan Bundle'a verip, veri aktarma işlemini nasıl yapacağımızı örnekleyelim.

Öncelikle şöyle bir senaryomuz olacak. BlankFragmet içerisinde bize veri sağlayacak etName isimli bir EditText ekledim. Buna göre de yeni XML dosyamız aşağıdaki gibi oluştu.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".BlankFragment">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/tvMessage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@string/hello_blank_fragment"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent" />

        <EditText
            android:id="@+id/etName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="Adınızı Giriniz"
            android:layout_marginTop="16dp"
            app:layout_constraintTop_toBottomOf="@id/tvMessage"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:importantForAutofill="no"
            android:inputType="text" />

        <Button
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            app:layout_constraintTop_toBottomOf="@id/etName"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:text="Nested Graph'a Git" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</FrameLayout>

BlankFragment.kt dosyamızı da aşağıdaki gibi güncelliyorum.

class BlankFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_blank, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        btn.setOnClickListener {
            val bundle = bundleOf("nameArg" to etName.text.toString())
            findNavController().navigate(R.id.navigation, bundle)
        }
    }

}

Koddan da anlaşılacağı üzere EditText' e girilen metni alıp, oluşturduğumuz bundle' ı NavController aracılığı ile hedef sayfamız olan BlankFragment2' ye gönderiyoruz.

Burada da gönderilen bundle'ı alarak, ekranda gösterimini sağlıyoruz.

class BlankFragment2 : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_blank_fragment2, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        tvMessage.text = "Diğer sayfadan gelen veri: " + arguments?.getString("nameArg")
    }
}

Safe Args kullanarak veri aktarımı

İlk olarak BlankFragment' ten ulaşacağım hedef olan BlankFragment4'e bir argüman geçmekle işe başlıyoruz. Bunun için nav_graph.xml dosyamızın dizayn bölümünü açarak aşağıdaki gibi BlankFragment4'ü seçili hale getiriyorum ve sağ taraftaki panelde bulunan Argument bölümünde + simgesine tıklıyorum.

Name alanına "nameField" yazıp, Type alanı için String seçiyorum. Add butonuna bastığımda XML yapısı da aşağıdaki gibi oluşacaktır.

<fragment
    android:id="@+id/blankFragment4"
    android:name="com.etiya.jpnavigation1.BlankFragment4"
    android:label="fragment_blank_fragment4"
    tools:layout="@layout/fragment_blank_fragment4">
    <action
        android:id="@+id/action_blankFragment4_to_blankFragment5"
        app:destination="@id/blankFragment5" />
    <argument
        android:name="nameField"
        app:argType="string" />
</fragment>

Gördüğünüz gibi Add Argument Link penceresinden giriş yaptığım bilgiler XML üzerinden argument tag'i ile blankFragment içerisinde eklenmiş oldu.

fragment_blank.xml dosyasını da aşağıdaki gibi güncelliyorum.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".BlankFragment">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/tvMessage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@string/hello_blank_fragment"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <EditText
            android:id="@+id/etName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:hint="Adınızı Giriniz"
            android:importantForAutofill="no"
            android:inputType="text"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tvMessage" />

        <Button
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Fragment 4'e Git"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/etName" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</FrameLayout>

BlankFragment.kt dosyamı kullanarak diğer sayfaya gidiş işlemini başlatabilirim.

class BlankFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_blank, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        btn.setOnClickListener {
            val action = BlankFragmentDirections.actionBlankFragmentToBlankFragment4(etName.text.toString())
            findNavController().navigate(action)
        }
    }

}

Kodumuzda BlankFragmentDirections bölümü dikkatinizi çekmiştir. NavDirection'ları yöneten ve Safe Args için eklediğimiz gradle plugin'inin ürettiği sınıflardan oluşuyor. Devamındaki actionBlankFragmentToBlankFragment4 metodu ise tanımladığınız action'ı, içerisindeki parametrede biraz önce tanımladığımız argümanı geçeceğiniz alanı belirtir.

Bu işlemi gerçekleştirdiğinizde Android Studio bazen kendini yenileyemeye biliyor. Generate edilen sınıfların aktif olması için Android Studio üzerinde Build > Clean Project ve Rebuild Project yaparsanız iyi olur.

Pekala, argümanımızı yukarıdaki gibi BlankFragment4'e göndermiş olduk. Peki nasıl alacağız? Bunun için de BlankFragment4.kt içerisine girip aşağıdaki gibi düzenliyoruz.

class BlankFragment4 : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_blank_fragment4, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        tvMessage.text = "Diğer sayfadan gelen veri: " + arguments?.getString("nameField")
    }

}

Uygulamamızın son hali de aşağıdaki gibi oluşacaktır.

Last updated