Navigation Component: Manuel Navigation Kıyası ve Kullanımı - Part I

Ahmet SIRIM
4 min readJul 10, 2023

Merhaba, bu iki yazılık serimde size Navigation Component kullanımının manuel navigation yönetimine kıyasla kolaylıklarından ve bu kütüphanenin kullanımınından bahsedeceğim.

Serinin ilk kısmı yani bu yazı, kütüphane kullanmadan navigation yönetimini içeriyorken ikinci kısmı ise Navigation Component kütüphanesi ile navigation yönetimini ve kütüphanenin sağladığı imkânları içeriyor. Kısaca tamamen kütüphane odağıyla yazıda bulunuyorsanız direkt Navigation Component: Manuel Navigation Kıyası ve Kullanımı - Part II yazısına atlayabilirsiniz.

FragmentManager ile Navigation

Bu kısımda, AndroidX Fragment library kütüphanesinden elde edilen yapıları, fonksiyonları kullanacağız. Bu sebeple en başta ya kütüphane linkinden ya da Setup your environment linkinden kütüphaneleri ekliyoruz.

Manuel navigation yönetimini, FragmentManager ve FragmentTransaction abstract class’larıyla yapılır.

FragmentManager & FragmentTransaction

FragmentManager, Fragment eklemek, kaldırmak, yerine başka bir Fragment koymak ve Fragment’ı back stack’e eklemek gibi işlemlerden sorumlu olan yani kısaca fragment transaction işlemlerinden sorumlu olan bir abstract class’tır.

FragmentTransaction, bir önceki paragrafta bahsettiğim işlemleri kullanıma sunar, sağlar. FragmentTransaction üzerinden tek işlem yapılacağı gibi birçok işlem de yapılabilir. İşlemler yapıldıktan sonra commit() fonksiyonuyla işlemler uygulanır, işlenir. Alttaki örnek kısmında kullandığım androidx.fragment.app (AndroidX Fragment library) kütüphanesinin commit() extension fonksiyonu, commit() fonksiyonunu arka planda kendi çağırır, değişikleri işletir ve bu şekilde daha rahat bir kullanım, deneyim sunar.

Back stack, Android işletim sistemi tarafından sağlanan bir Stack veri yapısıdır. Stack veri yapısı, birden fazla veriyi tutabilen ve push ile veri eklemeyi, pop ile ise veri çıkarmayı sağlayan temel iki işlemi gerçekleştiren bir veri yapısıdır.

Push ve pop işlemlerinin görselleştirilmiş hali
Push ve pop işlemlerinin görselleştirilmiş hali

Stack veri yapısındaki push ve pop işlemleri, yukardaki görseldeki gibi çalışır. Bir uygulama ekranlarında gezerken geri tuşuna basmamızla uygulamanın bize bir önceki bulunduğumuz sayfayı sunması, bu işleyiş ile aynı yaklaşımın bir ürünüdür.

Back stack kavramından sonra FragmentManager konusuna tekrar dönelim. FragmentManager class’ına en az FragmentActivty class’ının subclass’ı olan bir Activity içinden de herhangi bir Fragment içinden de erişebiliriz.

Bir Activity içinden FragmentManager class’ına erişmek için supportFragmentManager kullanırız.

FragmentManager erişimleri
FragmentManager erişimleri

Bir Fragment içinden FragmentManager sınıfına erişirken, dikkat etmemiz gereken iki durum vardır. Eğer Fragment, başka bir Fragment’i barındırıyorsa, barındırılan Fragment üzerinde işlem yapmak için childFragmentManager kullanırız. Eğer tam tersi bir durum söz konusu ise, yani barındırılan Fragment, barındıran Fragment üzerinde işlem yapmak istiyorsak parentFragmentManager kullanırız.

Bahsettiğim Fragment ekleme, kaldırma, yerine başka bir Fragment koyma ve Fragment’ı back stack’e ekleme işlemlerinin Activity içinde kullanımı temel olarak aşağıdaki gibidir.

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

backStackEntryCountToast(this, supportFragmentManager)

/** Add */

findViewById<Button>(R.id.button_add).setOnClickListener {
supportFragmentManager.commit {
setReorderingAllowed(true)
add<FirstFragment>(R.id.fragment_container_view)
}
backStackEntryCountToast(this, supportFragmentManager)
}

findViewById<Button>(R.id.button_add_with_back_stack).setOnClickListener {
supportFragmentManager.commit {
setReorderingAllowed(true)
add<FirstFragment>(R.id.fragment_container_view)
addToBackStack(null)
}
supportFragmentManager.commit {
setReorderingAllowed(true)
add<SecondFragment>(R.id.fragment_container_view)
addToBackStack(null)
}
supportFragmentManager.commit {
setReorderingAllowed(true)
add<ThirdFragment>(R.id.fragment_container_view)
addToBackStack(null)
}
backStackEntryCountToast(this, supportFragmentManager)
}

/** Replace */

findViewById<Button>(R.id.button_replace).setOnClickListener {
supportFragmentManager.commit {
setReorderingAllowed(true)
replace<SecondFragment>(R.id.fragment_container_view)
}
backStackEntryCountToast(this, supportFragmentManager)
}

findViewById<Button>(R.id.button_replace_with_back_stack).setOnClickListener {
supportFragmentManager.commit {
setReorderingAllowed(true)
replace<FirstFragment>(R.id.fragment_container_view)
addToBackStack(null)
replace<SecondFragment>(R.id.fragment_container_view)
addToBackStack(null)
}
backStackEntryCountToast(this, supportFragmentManager)
}

/** Remove */

findViewById<Button>(R.id.button_remove_first_fragment).setOnClickListener {
supportFragmentManager.commit {
setReorderingAllowed(true)
val firstFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container_view) as FirstFragment
remove(firstFragment)
}
backStackEntryCountToast(this, supportFragmentManager)
}

findViewById<Button>(R.id.button_remove_second_fragment).setOnClickListener {
supportFragmentManager.commit {
setReorderingAllowed(true)
val secondFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container_view) as SecondFragment
remove(secondFragment)
}
backStackEntryCountToast(this, supportFragmentManager)
}

}

override fun onBackPressed() {
super.onBackPressed()
backStackEntryCountToast(this, supportFragmentManager)
}

}

fun backStackEntryCountToast(context: Context, fragmentManager: FragmentManager) {
Toast.makeText(context, "${fragmentManager.backStackEntryCount}", Toast.LENGTH_SHORT).show()
}

Yukardaki kullanımdaki setReorderingAllowed fonksiyonunun true olması, aynı anda birden fazla transaction işlemi olacağı zamanlarda yani örneğin arada bir Fragment atlayıp bir sonraki Fragment’a geçileceği gibi durumlarda optimizasyon yapar, daha akıcı bir geçiş sağlar.

addToBackStack fonksiyonuyla Fragment back stack’e eklenir, bu fonksiyona girilebilecek olan name parametresi ile back stack state oluşturabilir ve bu state ile de back stack yönetimi yapılabilir. popBackStack fonksiyonuyla da onBackPressed fonksiyonu çalışınca da yani geri tuşuna basılınca da back stack tepesindeki Fragment, pop edilir.

Bu transaction işlemlerini denemenin önemli olduğunu düşünüyorum çünkü bence işleyişini anlamak için tanık olmanın gerekeceği kısımlar var. Örneğin yukardaki kullanımda button_add_with_back_stack butonuna her tıklanıldığında teker teker Fragment pop edilir fakat eğer yukardaki gibi değil de bir commit içinde 3 ekleme birden yapılırsa butona tıklanıldığında aynı anda 3 fragment da pop edilir. Bunun gibi denemeler yapmak isterseniz kaynak kodu: Transaction Examples. Temel olarak Android uygulamalarında manuel navigation yönetimi bu şekilde yapılır. Buradaki temel yönlendirmelerin ve daha detaylı navigation işlemlerinin Navigation Component ile yapılması üstüne odaklandığım Navigation Component: Manuel Navigation Kıyası ve Kullanımı - Part II yazımda görüşmek üzere :)

Kaynaklar:

Tavsiyeler, öneriler veya hatalı bulduğunuz kısımlar için Ahmet Sırım | LinkedIn veya Ahmet.SIRIM@outlook.com adresinden bana ulaşabilirseniz çok sevinirim. Yazıyı okuduğunuz için teşekkür ederim, başarılar :)

--

--