Android’ in yeni saklama alanı, Preferences DataStore

mert öztürk
ÇSTech
Published in
2 min readJan 3, 2023
Photo by CHUTTERSNAP on Unsplash

Android Jetpack kapsamında modern, güvenli ve hızlıca yerel olarak veri saklamak için geliştirmiş bir kütüphane olan DataStore, anahtar-değer ikilisi veya karmaşık tipteki nesneleri saklamayı, düzenlemeyi ve sağlamayı hedefliyor.

İhtiyaçlara göre ayrışmış iki farklı uygulaması mevcut;
Preferences DataStore; anahtar(key) karşılığı int, boolean gibi ilkel veri tiplerini saklamayı amaçlıyor ve Android tarafında yeni Shared Preferences olmayı hedefliyor.
Proto DataStore; Protocol Buffers kullanarak daha karmaşık veri tipleriyle çalışabilmeyi sağlıyor.

Preferences DataStore

DataStore’ nin bize sağladığı yeteneklere hızlıca bir giriş yapalım.

implementation "androidx.datastore:datastore-preferences:1.0.0"

Projemizde preferences kullanacağımız durumda build.gradle dosyasına ekleme yapmamız yeterli :)

//DataStore için bir değişken ismi ve eşsiz bir isim vermeniz gerekiyor.
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore("benim_datastore")

Artık Context kullanarak datastore’ ye erişebilir durumdayız.
Preferences DataStore anahtar-değer kullanarak çalıştığından bahsetmiştim. Saklamak istediğimiz değer için eşsiz olacak şekilde anahtarlar belirlememiz gerekecek. Bunları bir sınıf içinden yönetmek hem daha kolay hem daha güvenli olmasını sağlayacaktır. Bu sebeple örneğin aşağıda olduğu gibi bir sınıf oluştursak.

class MyDataStore(private val dataStore: DataStore<Preferences>) {

private object Keys {
val ORNEK_ANAHTAR: Preferences.Key<Boolean> = intPreferencesKey("essiz_anahtar")
}

}

Bu şekilde boolean tipinde ve "essiz_anahtar" isimli değere erişim anahtarı oluşturmuş olduk. Ayrıca tüm ilkel veri tipleri için bunun gibi bir erişim anahtarı oluşturucu fonksiyon bulunmakta

  • intPreferencesKey(name: String)
  • doublePreferencesKey(name: String)
  • stringPreferencesKey(name: String)
  • booleanPreferencesKey(name: String)
  • floatPreferencesKey(name: String)
  • longPreferencesKey(name: String)
  • stringSetPreferencesKey(name: String)

Bu anahtarlar sayesinde artık veriler üzerinde çalışabiliriz.

//Veriye erişmek için
suspend fun getOrnek(){
dataStore.data.catch {
//IOException gelebilir.
}.map { it[Keys.ORNEK_ANAHTAR] }.firstOrNull()
}

//Veriyi düzenlemek için
suspend fun setOrnek(value: Int){
dataStore.edit {
it[Keys.ORNEK_ANAHTAR] = value
}
}

Ortak bir yapı altında erişimleri sağlayarak kod tekrarının önüne geçebiliriz.

//Bu şekilde her anahtar için tekrarlı kod yapılarını kullanmak yerine ve shared pref gibi bir kullanım için
//Veriyi düzenlemek için
private suspend fun <T> Preferences.Key<T>.setValue(value: T) {
dataStore.edit { preferences -> preferences[this] = value }
}

//Veriye erişim sağlamak için
private suspend fun <T> Preferences.Key<T>.getValue(defaultValue: T): T {
return dataStore.data.handleError()
.map { preferences -> preferences[this] }
.firstOrNull() ?: defaultValue
}

//DataStore preferences e erişirken IOException alma şansı bulunuyor.
private fun Flow<Preferences>.handleError(): Flow<Preferences> {
this.catch { exception ->
if (exception is IOException) {
emit(emptyPreferences())
} else {
throw exception
}
}
return this@handleError
}

Böylece artık hızlıca verilerimizi yönetebiliriz.

//Veriye erişmek için
suspend fun getOrnek(){
Keys.ORNEK_ANAHTAR.getValue(-1)
}

//Veriyi düzenlemek için
suspend fun setOrnek(value: Int){
Keys.ORNEK_ANAHTAR.setValue(value)
}

Artık veri ekleme ve düzenleme yapabiliyoruz. Ama bir şeyi farketmiş olabilirsiniz, veriye erişimde Flow<Preferences> akışının ilk değerini okuyoruz. Peki bu durumda sürekli her değişimden haberdar olabilir miyiz?

Tabiki evet :) Bunun için aşağıdaki yardımcı fonksiyonu kullanabilirsiniz.

private fun <T, M> Preferences.Key<T>.watchValue(defaultValue: T, mapper: (T?) -> M?): Flow<M?> {
return dataStore.data
.handleError()
.map { preferences ->
mapper(preferences[this] ?: defaultValue)
}
}

Preferences DataStore’ yi anlatmaya çalıştığım bu yazımda zaman ayırıp okuduğunuz için teşekkür ederim. Clap’ lamadan geçmeyin 😄

İyi günler, iyi çalışmalar dilerim. Sonraki yazılarda görüşmek üzere

Kaynaklar:
https://developer.android.com/topic/libraries/architecture/datastore

--

--