Object Passing in Navigation Compose — 2 | by Gökhan Akbaş | May, 2024

Bu yöntemde öncelikle Gson kütüphanesini projemize eklememiz gerekiyor.

Android Projemizin build.gradle.kts(Module:app) dosyasına aşağıdaki gibi ekleme yapmamız gerekiyor.

implementation ("com.google.code.gson:gson:2.8.6")

Yine önceki yazımda size gösterdiğim Navigation Compose u NavGraph.kts ve Screen.kts lar üzerinden anlatmaya devam edeceğim.

Bu noktada Screen class ımızda her sayfanın bir “unique route” nu oluşturmuştuk.Ancak route lar üzerinden parametre iletmeyi konuşmamıştık.

Şimdi bir route da ;

  • parametre nasıl eklenir ?
  • parametre tipi nasıl belirlenir ?
  • parametre karşı tarafta nasıl alınır?
  • eğer bir parametre byte boyutunda taşma olursa ne olur ?

bunlardan konuşacağız.

Parametre nasıl eklenir?

İlk olarak Screen class ımızın data object lerimizin önceki halini bir görelim

Screen.kts(Parametresiz) :

sealed class Screen(var route: String) {

data object ProductEntryPage : Screen("productEntryPage")

data object ProductMainPage : Screen("productMainPage")

}

Parametre olarak EntryPage e bir Integer tipinde veri gönderdiğimizi ve MainPage e bir Product nesnesi gönderdiğimizi varsayalım.

Screen.kts(Parametreli) :

sealed class Screen(var route: String) {

data object ProductEntryPage : Screen("productEntryPage/{productId}"){
fun passNavigate(productId: Int): String {
route = "productEntryPage/$productId"
return route
}
}

data object ProductMainPage : Screen("productMainPage/{productObject}"){
fun passNavigate(productObject: Product): String {

val gson = Gson()
val productJson= gson.toJson(productObject) // Bu satır bizim nesnemizi String tipinde bir Json a çevirecek.
route = "productMainPage/$productJson"

return route
}
}

}

passNavigate() fonksiyonunun kullanımı için örnek bir senaryo :

Button(
onClick={
val product = Product(name="Bread",price=10)
navController.navigate(Screen.ProductMainPage.passNavigate(product))
}
)
Button(
onClick={
val product_id = 5
navController.navigate(Screen.ProductEntryPage.passNavigate(product_id))
}
)

Böylelikle bizim route da /{productId} veya /{productObject} olarak bıraktığımız kısmı passNavigate() ile doldurup yeni route u geriye dönderdik.

Şimdi bu verileri route a koyduktan sonra route dan geri alıp sayfalarımıza nasıl yerleştireceğiz ona bakalım.

Artık route dan verileri alma işlemimiz NavGraph.kt dosyamızda devam edecek.

Önce NavGraph.kt nin eski halini görelim.

@Composable
fun AppNavGraph(
navController: NavHostController
) {

val sharedViewModel = SharedViewModel()

NavHost(
navController = navController,
startDestination = Screen.ProductEntryPage.route
)
{

composable(Screen.ProductEntryPage.route) {
EntryPage(navController = navController)
}
composable(Screen.ProductMainPage.route) {
MainPage(navController = navController)
}

}
}

Şimdi bizim composable fonksiyonunda argüman geleceğini belirtmemiz gerekiyor bu işlemler aşağıdaki gibi yapılmalıdır.

@Composable
fun AppNavGraph(
navController: NavHostController
) {

val sharedViewModel = SharedViewModel()

NavHost(
navController = navController,
startDestination = Screen.ProductEntryPage.route)
{

composable(Screen.ProductEntryPage.route,arguments=listOf(
navArgument("productId") {
type = NavType.IntType
}
)) { backStack->
val newProductId= backStack.arguments?.getInt("productId")!! //Buradaki productId route üzerindeki parametre adıyla aynı olmalı
EntryPage(navController = navController, product_id = new_product_id )
}
composable(Screen.ProductMainPage.route,arguments=listOf(
navArgument("productObject") {
type = NavType.StringType
}
)) {
val newProductJson= backStack.arguments?.getString("productObject")!! //Buradaki productObject route üzerindeki parametre adıyla aynı olmalı
val gson= Gson()
val newProductObject=gson.fromJson(newProductJson,Product::class.java) //Gelen Json ı ve hangi class tipinde nesneye dönüştürüleceğini belirtiyoruz.
MainPage(navController = navController , productObject= newProductObject)
}

}
}

composable fonksiyon içinde arguments e bir listOf ve içerisinde navArgument tipinde elemanlar verdik. Bu şu anlama geliyor route a birden fazla parametre verebilirsiniz.Nasıl?

Screen.kt :

data object ProductEntryPage : Screen("productEntryPage/{product_id}/{product_name}"){
fun passNavigate(productId: Int , productName : String): String {
route = "productEntryPage/$productId/$productName"
return route
}
}

NavGraph.kt

composable(Screen.ProductEntryPage.route,arguments=listOf(
navArgument("productId") {
type = NavType.IntType
},navArgument("productName"){
type= NavType.StringType
}
)) { backStack->
val newProductId= backStack.arguments?.getInt("productId")!! //Buradaki productId route üzerindeki parametre adıyla aynı olmalı
val newProductName= backStack.arguments?.getString("productName")!!
EntryPage(navController = navController, productId = newProductId , productNamr=newProductName)
}

Böylelikle nesne aktarmanın yolunu ve normal primitive tipteki verilerin route yoluyla aktarımını anlatmış olduk.

Ancak bu yöntemi kullanmayı çok tercih etmiyorum çünkü bana göre 2 önemli sorunu var.

1- Sınırlı boyut

2- Karmaşıklık

3- Kütüphane bağımlılığı

1-Sınırlı Boyut : Eğer nesnemiz String tipinin boyutunu(255 karakter) aşarsa uygulamamız patlıyor.Bunun için örnek senaryo , eğer bir Product ın açıklama parametresi olsaydı ve bu açıklama bir ürün için bir paragraf olsaydı bunu bu şekilde aktaramazdık.Uygulama patlardı.

Json String dönderir.

2- Karmaşıklık : Bu işlemlerin iki class dada dikkat edilmesi gereken null gelmeyecek operatörü ( !! ) gibi şeylerle dikkatlice yapılması gerek.

Karmaşıklık

3-Kütüphane Bağımlılığı : Belkide işimizi bazı durumlarda göremeyecek bir yöntem için dışarıdan kütüphane eklememiz gerekiyor.Bu tarz işlemler tabi uygulamanın performansı küçük de olsa etkilemektedir.Bir de SuperApp gibi uygulama yaptığınızı düşünün.

Bu yazımda da sizlere route üzerinden veri göndermeyi ve Gson ile de nesne aktarmayı gösterdim.

Okuduğunuz için teşekkür ederim 🙂

Leave a Comment

Scroll to Top