DEV Community

Cengiz TORU
Cengiz TORU

Posted on • Originally published at cengiztoru.Medium on

5 3

Android Jetpack Navigation Component #2 Fragmentler Arası Veri Taşıma İşlemleri

Bir önceki yazımı okumadıysanız lütfen okuduktan sonra bu yazıyı okuyun. Okumamanız halinde bu yazıdakileri anlayamayabilirsiniz.

Navigation Architecture Component #1 Ekranlar Arası Geçiş İşlemleri

Ekranlar arası geçiş yaparken sıklıkla veri taşıma ihtiyacımız olur. Bu yazıda Navigation Component ile ekranlar arasında nasıl veri taşıyabileceğimizi anlatmaya çalışacağım. Keyifli okumalar.

Öncelikle şunu belirtmek istiyorum. Veri taşımanın en hızlısı, en hafifi, kısacası best-practise yöntemi bundle ile taşımaktır. Primitive tipteki veriler direk o verinin tipindeki fonksiyon yardımıyla bundle’a eklenerek taşınabilir. Obje taşırken de modeli parcelable dizayn ederek bundle’ın parcelable fonksiyonu yardımıyla bundle’a eklenerek taşınabilir.

Google ekranlar arası veri taşırken büyük verilerin taşınmamasını, veriye ait bir id / key değerinin taşınmasının önermektedir. Çünkü Android’de kayıt edilen veriler için toplam alan sınırlıdır.

Büyük veriler taşımak için burayagöz atabilirsiniz.

Bu kadarcık teoriden sonra artık kodlama kısmına geçebiliriz 💻.

PRIMITIVE TİPTEKİ VERİLERİ GEÇİŞ ESNASINDA TAŞIMA

Öncelikle NavigationGraph’ta verilerin taşınacağı ekrana taşınacak verileri tanımlamamız lazım.

<fragment
android:id="@+id/homeFragment"
android:name="com.cengiztoru.samplenavigationexample.ui.fragments.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home">
<argument
android:name="email"
app:argType="string"
android:defaultValue="none" />
<argument
android:name="userId"
app:argType="integer"
android:defaultValue="-1" />
<argument
android:name="isActive"
app:argType="boolean"
android:defaultValue="false" />
</fragment>

Navigation Graph dosyamızın içinde Fragmente gönderilecek veriler yukarıdaki gibi argument tagleri arasında tanımlanabilir. Gerekmesi halinde argumentin nullable olma durumuda app:nullable=”true veya false” şeklinde eklenebilir.

Şimdi de verileri ilgili ekrana nasıl gönderebileceğimize bakalım.

//PASS DATA WITHOUT SAFE ARGS, PASS DATA BY SIMPLE BUNDLE
val bundle = Bundle()
bundle.putString("email", etMail.text.toString())
bundle.putInt("userID", 123)
bundle.putBoolean("isActive",false)
// ...
navController.navigate(R.id.action_loginFragment_to_homeFragment, bundle)

Primitive tipteki verileri yukarıdaki koddaki gibi gönderebiliriz. Öncelikle bir bundle nesnesi oluşturuyoruz. Ardından verilerimizi bundle nesnesinin verimizin tipi ile aynı olan fonksiyonu yardımıyla bundle nesnesine ekliyoruz. Bir önceki yazıda ekranlar arası geçiş yapmayı öğrenmiştik. Ekranlar arası geçiş yaparken navigate fonksiyonuna bundle nesnesini 2. parametre olarak vererek verilerimizi taşıyabiliriz.

Son olarak ilgili ekrana taşınanan verileri nasıl yakalayacağımıza bakalım.

lateinit var email: String
lateinit var userID: Int
lateinit var isActive: Boolean
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
email = arguments!!.getString("email")!!
userID = arguments!!.getInt("userId")!!
isActive = arguments!!.getBoolean("isActive")!!
}
view raw HomeFragment.kt hosted with ❤ by GitHub

Verilerimizi onCreate metodunda yukarıdaki şekilde elde edebiliriz.

GEÇİŞ ESNASINDA NESNELERİ TAŞIMA

Öncelikle modelimizi Parcelable olacak şekilde hazırlayalım.

@Parcelize
data class User(val email: String, val name: String, val surname: String) : Parcelable
view raw User.kt hosted with ❤ by GitHub

Daha sonra veri göndereceğimiz ekrana modelimiz için bir argument ekleyelim.

<fragment
android:id="@+id/homeFragment"
android:name="com.cengiztoru.samplenavigationexample.ui.fragments.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home">
<argument
android:name="user"
app:argType="com.cengiztoru.samplenavigationexample.data.User"
app:nullable="false" />
</fragment>

Burada argType olarak modelimizin tam yolunu vermeye dikkat edelim.

Daha sonra bu ekrana verilerimizi navigate fonksiyonu ile gönderelim.

val bundle = Bundle()
bundle.putParcelable("user", getUserData())
navController.navigate(R.id.action_loginFragment_to_homeFragment, bundle)
// ************************************************************************************
//TODO YOU CAN CUSTOMIZE HERE FOR YOU
private fun getUserData() = User(etMail.text.toString(), "Cengiz", "TORU")

Öncelikle bir bundle nesnesi oluşturuyoruz. Daha sonra bundle nesnesinin putParcelable fonksiyonuna verimizi ekliyoruz. Son olarak bundle nesnemizi navigation controller nesnemizin navigate fonksiyonuna 2. parametre olarak veriyoruz. Bu şekilde (nesne olan) verimizi ilgili ekrana gönderebiliriz.

Şimdi ilgili ekranda gelen veriyi nasıl yakalayabileceğimize bakalım.

lateinit var user: User
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
user = arguments!!.getParcelable<User>("user")!!
}
view raw HomeFragment.kt hosted with ❤ by GitHub

Gönderilen veriyi arguments nesnesinin getParcelable fonksiyonu ile elde edebiliriz.

Şimdi dananın kuyruğunun koptuğu yere geldik. Lütfen dayanın bundan sonraki başlık önemli.

SAFE ARGS İLE VERİ TAŞIMA

SafeArgs gradle plugini Navigation Components ile geldi. SafeArgs ile verileri taşırken Type-Safety veriler taşıyabiliyoruz.

Type-Safety kavramının ne olduğunu, önemini bilmiyorsanız aşağıdaki yazımı okuyabilirsiniz.

Type Safety (Tip — Tür Güvenliği)

SafeArgs yapısını kullanabilmek için bazı ayarlar yapmamız gerekiyor.

Öncelikle AndroidX kullanımını gradle.properties dosyamızda android.useAndroidX=true koduyla açmış olduğumuzdan emin olmamız gerekiyor.

Daha sonra build.gradle(Module: app) dosyamızın başına sadece kotlinde kullanmak için

apply plugin: "androidx.navigation.safeargs.kotlin"
Enter fullscreen mode Exit fullscreen mode

Javada veya hem Javada hem Kotlinde kullanabilmek için

apply plugin: "androidx.navigation.safeargs"
Enter fullscreen mode Exit fullscreen mode

eklememiz gerekiyor.

Daha sonra build.gradle(Project: …) dosyamıza

buildscript {
   dependencies {
        def nav_version = "2.3.0"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

Enter fullscreen mode Exit fullscreen mode

eklememiz gerekiyor. Bunları yaptıktan sonra projemizi Rebuild edelim. SafeArgs, ekranlarımızın isminin sonuna Directions eklenmiş sınıflar oluşturacaktır. Ör: LoginFragment için LoginFragmentDirections

SafeArgs kullanmak için argument tanımında ve veriyi ilgili ekranda yakalama adımlarında herhangi bir değişiklik yapmıyoruz.

Şimdi SafeArgs ile nasıl veri gönderdiğimize bakalım.

val user = getUserData()
val action = LoginFragmentDirections.actionLoginFragmentToHomeFragment(user)
navController.navigate(action)
// ************************************************************************************
//TODO YOU CAN CUSTOMIZE HERE FOR YOU
private fun getUserData() = User(etMail.text.toString(), "Cengiz", "TORU")

Verimizi SafeArgs tarafından oluşturulmuş olan (sonu Directions ile biten) sınıfın içindeki, gerçekleşmesini istediğimiz ekran geçişinin bulunduğu fonksiyona parametre olarak veriyoruz. Bu fonksiyon ismini NavigationGraph içindeki action taglerininin id attributelerinden alır. Fonksiyon bize NavDirections tipinde bir nesne döndürür. NavigationController nesnesinin navigate fonksiyonuna bu nesneyi verirsek ekran geçişi sağlanmış olacak.

SAFEARGS KULLANSAK NE OLUR? KULLANMASAK NE OLUR?

Şimdi SafeArgs yapısının avantajına bakalım. SafeArgs ile veri taşırken Tip Güvenliğinin sağlandığından bahsetmiştim. Şimdi ona bakalım.

Dalgınlıkla verileri gönderirken yanlış veri tipinde veri göndermeye çalışmamız halinde (yukarıdaki resimdeki gibi) IDE bizi uyarır. Varsayalım ki dalgınlığımız o kadar üzerimizde ki uyarıyı görmedik bu sefer de projeyi compile ederken hata alırız.

Böylece uygulama canlıya çıktıktan sonra olabilecek hatalar uygulama canlıya çıkmadan önlenmiş olur.

Peki SafeArgs kullanmazsak ne olur?

SafeArgs kullamazsak veri taşırken Type-Safety validasyonu yapılmaz. Bu da yanlış tipte veri göndermemiz halinde hata almamaz, hatta projenin sorunsuz build edilmesi demek olur. Ancak uygulama hata yaptığımız yeri çalıştırmaya çalıştığında çökecektir.

Örneğin HomeFragment bizden bir User nesnesi beklerken biz User tipinden farklı tipte veri gönderecek olursak (SafeArgs kullanmıyorsak) hiç hata almayız. Projemiz de derlenir. Ama verilerin gönderildiği ekran verileri yakalamaya çalışırken yakalayamayacak ve uygulama çökecektir.

Acil bir şekilde canlıya çıkan, testi az yapılabilmiş bir projede böyle bir hata başımızı fazlasıyla ağrıtabilir. Bu tarz durumların oluşmaması için SafeArgs kullanmanızı tavsiye ederim.

Gönderilen verileri yakalarken yukarıdaki koda alternatif olarak şu şekilde bir kod parçacığı da kullanılabilir.

lateinit var user: User
val args: HomeFragmentArgs by navArgs()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
user = args.user
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false)
}
view raw HomeFragment.kt hosted with ❤ by GitHub

Bu yazımda Navigation Component ile ekranlar arasında nasıl veri taşıyabileceğimizi anlatmaya çalıştım. Olabildiğince Türkçe kaynak oluşturmaya çalışıyorum. Ama malumunuz sektörün dili İngilizce. Bu sebeple de bazı kelimeler İngilizce kalıyor. Çünkü ya Türkçe’si yok yada Türkçe’si anlamsız oluyor. Bunu anlayışla karşılayacağınızı umuyorum.

Yazıyı beğendiyseniz 👏 butonuna basarsanız sevinirim. Daha fazla insanın faydalanması için paylaşmanızı rica ederim. Buna benzer yazıları yazmaya devam etmeyi düşünüyorum. Yazdıklarımdan haberdar olmak için takip edebilirsiniz. Sonraki yazı da görüşmek üzere.

LİNKLER

cengiztoru/Simple-Navigation-Component-Example

Navigation Component Google Guide

Navigation Component Google Pass Data

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up