SharedPreferences, basit ayarları ve uygulama yapılandırmalarını kaydetmek için tasarlanmış bir Android anahtar-değer veri deposudur. Veriler, cihazda bir XML dosyasında saklanır ve yalnızca onu oluşturan uygulama içinde erişilebilir. Resmi belgelere göre Android Developers, 2025, SharedPreferences ilkel türlerin depolanmasını destekler: String, Int, Boolean, Float, Long ve Set<String>. Bu, SQL sorgularına veya dosya sistemiyle doğrudan çalışmaya gerek kalmadan küçük miktarlarda kullanıcı ayarını kaydetmek için en basit ve en hızlı çözümdür.
Anahtar Noktalar
SharedPreferences, cihazın dahili deposunda bir XML dosyasında anahtar-değer çiftlerini depolamak için yerleşik bir Android mekanizmasıdır. API Level 1'den beri kullanılabilir ve ek kütüphane gerektirmez. Temel amacı, kullanıcı tercihlerini, arayüz durumunu, ilk başlatma işaretlerini ve yapılandırılmış bir veritabanı gerektirmeyen diğer basit verileri kaydetmektir.
Her SharedPreferences dosyası belirli bir ad ve erişim moduyla ilişkilendirilir. Varsayılan olarak, dosyaya erişimi yalnızca geçerli uygulamayla sınırlayan Context.MODE_PRIVATE modu kullanılır. Daha önce Android, MODE_WORLD_READABLE ve MODE_WORLD_WRITEABLE modlarını destekliyordu, ancak bunlar API Level 17'den itibaren kullanımdan kaldırıldı ve güvenlik nedenleriyle Android 7.0'da (API 24) tamamen kaldırıldı.
Basitliğine rağmen, SharedPreferences milyonlarca Android uygulamasında kullanılmaktadır. Google'a göre, Google Play'de yayınlanan uygulamaların %90'ından fazlası ayarları depolamak için SharedPreferences kullanır. Ancak karmaşık senaryolar (büyük veri hacimleri, tür güvenliği, eşzamansızlık) için Google, Android Jetpack kütüphanesinden Preferences DataStore gibi daha modern çözümler önermektedir.
Fiziksel olarak, SharedPreferences uygulama dizininde bir XML dosyası olarak saklanır: /data/data/{package_name}/shared_prefs/{file_name}.xml. Dosya, depolanan değer türüne bağlı olarak bir kök öğe <map> ve alt öğeler <string>, <int>, <boolean>, <float> ve <long> içerir. Dosya boyutu sınırlı değildir, ancak büyük veri hacimlerinde (100 KB'ın üzerinde) okuma ve yazma performansı belirgin şekilde düşmeye başlar.
SharedPreferences dosyaları varsayılan olarak şifrelenmez. Veriler, cihazın dosya sisteminde düz metin olarak saklanır. Hassas verileri (token'lar, şifreler) depolamak için, AES256-GCM kullanarak anahtarları ve değerleri otomatik olarak şifreleyen AndroidX Security kütüphanesinden EncryptedSharedPreferences kullanılması önerilir.
SharedPreferences, periyodik disk senkronizasyonuyla bellek içi önbellekleme prensibiyle çalışır. Dosyaya ilk erişimde (getSharedPreferences aracılığıyla), Android XML dosyasını RAM'e yükler ve bir Map nesnesine ayrıştırır. Sonraki tüm okuma işlemleri, diskten yeniden okumadan bellekten gerçekleştirilir. Bu, yüksek veri erişim hızını garanti eder.
Yazma işlemleri Editor — bir iç değişiklik arabelleği kullanır. Geliştirici putString veya putBoolean çağırdığında, değişiklikler bellekteki Editor nesnesinde saklanır. Diske gerçek yazma, commit (eşzamanlı) veya apply (eşzamansız) yöntemi çağrıldığında gerçekleşir. Bu yöntemler çağrılana kadar veriler kaydedilmez ve uygulama beklenmedik şekilde çökerse değişiklikler kaybolabilir.
Bir SharedPreferences örneği almak için iki yöntem kullanılır: getPreferences ve getSharedPreferences. İlki yalnızca bir Activity içinde kullanılabilir ve Activity adıyla bir dosya oluşturur. İkincisi daha esnektir, bir dosya adı ve erişim modu kabul eder ve herhangi bir bağlamdan (Application, Activity, Service) erişilebilir. Uygulamanın modülüne veya işlevselliğine karşılık gelen bir dosya adıyla getSharedPreferences kullanılması önerilir.
// SharedPreferences alınması
val prefs = context.getSharedPreferences(
"user_settings", Context.MODE_PRIVATE
)
// Veri yazma
with(prefs.edit()) {
putString("username", "Anna")
putInt("age", 28)
putBoolean("isLoggedIn", true)
apply()
}
// Veri okuma
val username = prefs.getString("username", "")
val age = prefs.getInt("age", 0)
val isLoggedIn = prefs.getBoolean("isLoggedIn", false)
MODE_MULTI_PROCESS (kullanımdan kaldırıldı) kullanıldığında, SharedPreferences işlemler arasında senkronize olur. Ancak bu senkronizasyon atomikliği garanti etmez ve Google, çoklu işlem senaryolarında SharedPreferences kullanımından kaçınılmasını önerir. Bu gibi durumlarda ContentProvider, işlemler arası erişimli Room veya DataStore kullanmak daha iyidir.
SharedPreferences, anahtarla veri okumak için bir dizi yöntem ve yazmak için Editor arayüzü sağlar. Her okuma yöntemi iki parametre alır: bir anahtar ve anahtar bulunamazsa döndürülen varsayılan bir değer. Varsayılan değer ayrıca dönüş türünü de belirler: getString String döndürür, getInt Int döndürür, vb.
| Okuma yöntemi | Yazma yöntemi | Veri türü |
|---|---|---|
| getString | putString | String |
| getInt | putInt | Int |
| getBoolean | putBoolean | Boolean |
| getFloat | putFloat | Float |
| getLong | putLong | Long |
| getStringSet | putStringSet | Set<String> |
Editor, bir arabellekte değişiklikleri toplayan SharedPreferences'ın iç bir nesnesidir. Tüm değişiklikler yapıldıktan sonra geliştirici commit() (eşzamanlı yazma) veya apply() (eşzamansız yazma) çağırır. Fark kritiktir: commit, diske tam yazma tamamlanana kadar geçerli iş parçacığını bloke eder ve bir boolean (başarı/başarısızlık) döndürürken, apply yazmayı bir arka plan iş parçacığında gerçekleştirir ve kontrolü hemen geri verir ancak sonuç döndürmez.
Yazma sonucunu bilmenin gerekli olmadığı tüm durumlarda commit yerine apply kullanılması önerilir. apply daha hızlıdır ve UI iş parçacığını bloke etmez. commit yalnızca verilerin başarıyla kaydedilip kaydedilmediğini bilmenin kritik olduğu durumlarda veya çoklu işlem modunda çalışırken kullanılmalıdır. Tek tek anahtarları kaldırmak için remove yöntemi, tamamen temizlemek için clear kullanılır. Tüm silme işlemleri de Editor aracılığıyla gerçekleştirilir.
// Birden çok değişiklik - tek apply
prefs.edit {
putString("theme", "dark")
putBoolean("notifications", false)
remove("old_key")
}
// Değer değişikliği dinleyicisi
prefs.registerOnSharedPreferenceChangeListener { prefs, key ->
Log.d("TAG", "Anahtar değişti: $key")
}
Android 12'den (API 31) itibaren, SharedPreferences, Lifecycle aracılığıyla otomatik abonelik iptali ile registerOnSharedPreferenceChangeListener desteğiyle geliştirilmiştir. Bu, unutulan dinleyicilerle ilişkili bellek sızıntılarını önlemeye yardımcı olur. Eski sürümlerde, geliştiricinin bileşenin onDestroy veya onStop'unda manuel olarak unregisterOnSharedPreferenceChangeListener çağırması gerekir.
Yaygın kullanımına rağmen, SharedPreferences Android'deki tüm veri depolama senaryoları için evrensel bir çözüm değildir. Veri hacmine, tür güvenliği gereksinimlerine ve performansa bağlı olarak Google, Android Jetpack ve standart Android kütüphanesinde bulunan çeşitli alternatifler önermektedir.
| Çözüm | Ne zaman kullanılmalı | Dezavantajlar |
|---|---|---|
| SharedPreferences | Küçük ayarlar (100 anahtara kadar) | Tür güvenliği yok, eşzamanlı okuma |
| DataStore | Coroutine ile orta karmaşıklıkta ayarlar | API 14 altında geriye dönük uyumluluk yok |
| Room | Yapılandırılmış veriler ve listeler | 3-5 ayar için aşırı |
| EncryptedSharedPreferences | Hassas veriler ve token'lar | AndroidX Security'ye bağımlılık |
DataStore, Google tarafından SharedPreferences'ın yerine geçmek üzere sunulan bir Android Jetpack kütüphanesidir. İki varyant sunar: Preferences DataStore (SharedPreferences gibi anahtar-değer) ve Proto DataStore (Protocol Buffers aracılığıyla türkçe depolama). DataStore, eşzamansız çalışma için coroutine ve Flow kullanır, tür güvenliğini garanti eder ve sürüm geçişlerini otomatik olarak yönetir. Google, tüm yeni projeler için DataStore önermektedir.
DataStore'un ana avantajı API düzeyinde eşzamansızlıktır. Tüm okuma işlemleri Flow döndürür ve yazma işlemleri suspend işlevleridir. Bu, SharedPreferences'ın eşzamanlı okumasında oluşabilecek UI iş parçacığı blokajını tamamen ortadan kaldırır. Ayrıca DataStore, veri tutarlılığını garanti eder: yazma bir işlemde gerçekleştirilir ve başarısız olursa tüm değişiklikler geri alınır.
Pratik bir örnek düşünelim: Bir Android uygulamasında tema ayarları (açık/koyu/sistem). Kullanıcı bir tema seçer ve seçim SharedPreferences'a kaydedilir. Sonraki uygulama başlatmalarında, tema kaydedilen ayarlardan geri yüklenir. Tepkisel UI güncellemeleri için, SharedPreferences.OnSharedPreferenceChangeListener aracılığıyla değişiklikleri izleme kullanılır.
Tema için SharedPreferences ile tüm çalışmayı kapsülleyen bir ThemePreferences sınıfı oluşturalım. Sınıf, getTheme (okuma), setTheme (yazma) ve observeTheme (izleme) yöntemlerini sağlar. Ayarlar dosyasının adı MODE_PRIVATE moduyla “app_preferences” olacaktır. Kolaylık için anahtarlar, bir companion nesnesinde sabitler olarak yerleştirilir.
class ThemePreferences(context: Context) {
companion object {
private const val PREF_NAME = "app_preferences"
private const val KEY_THEME = "theme_mode"
const val THEME_LIGHT = "light"
const val THEME_DARK = "dark"
const val THEME_SYSTEM = "system"
}
private val prefs = context
.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
fun getTheme(): String =
prefs.getString(KEY_THEME, THEME_SYSTEM) ?: THEME_SYSTEM
fun setTheme(theme: String) {
prefs.edit { putString(KEY_THEME, theme) }
}
fun observeTheme(callback: (String) -> Unit) {
prefs.registerOnSharedPreferenceChangeListener { _, key ->
if (key == KEY_THEME) {
callback.invoke(getTheme())
}
}
}
}
Bir Activity veya Fragment'te, ThemePreferences örneği almak uygulama bağlamı aracılığıyla yapılır. Başlatma sırasında, geçerli temayı ayarlamak için getTheme çağrılır. Kullanıcı yeni bir tema seçtiğinde setTheme çağrılır ve observeTheme aracılığıyla Activity yeniden başlatılmadan arayüz güncellenir. Bellek sızıntılarını önlemek için onDestroy'de dinleyiciden aboneliği iptal etmek önemlidir, özellikle yapılandırma değişikliğinde Activity yeniden oluşturuluyorsa.
Minimum hedef sürümü Android 12+ olan uygulamalar için, LifecycleObserver ile birlikte registerOnSharedPreferenceChangeListener kullanılması önerilir. Bu, bileşen yaşam döngüsü değişikliklerinde abonelik ve abonelik iptalini otomatik olarak yönetir. Eski sürümlerde, abonelik ve abonelik iptali manuel olarak yönetilmelidir, bu da SharedPreferences kullanan üretim uygulamalarında sık görülen bir hata kaynağıdır.
Sıkça Sorulan Sorular
SharedPreferences doğrudan yalnızca ilkel türleri ve Set<String>'i destekler. Nesneleri depolamak için, bunları Gson veya Moshi aracılığıyla bir JSON dizesine serileştirmek, putString ile kaydetmek ve okurken seri durumdan çıkarmak gerekir. Çok sayıda alana sahip karmaşık nesneler için, JSON serileştirmesiyle SharedPreferences yerine Room kullanılması önerilir.
Evet, SharedPreferences iş parçacığı güvenlidir. Tüm okuma ve yazma işlemleri, SharedPreferences nesnesi ve Editor'u düzeyinde senkronize edilir. Ancak çoklu işlem modu kullanıldığında senkronizasyon garanti edilmez. Tek bir uygulama içinde birden çok iş parçacığından eşzamanlı erişim için SharedPreferences, ek kilitler olmadan güvenlidir.
SharedPreferences'tan tüm verileri tamamen temizlemek için Editor'de clear() yöntemini çağırın ve değişiklikleri apply aracılığıyla uygulayın. XML dosyasının kendisini silmeniz gerekiyorsa, bağlamda deleteSharedPreferences(name) kullanın. Ayarlar → Uygulamalar → Verileri temizle yoluyla uygulama verilerini temizlemek de tüm SharedPreferences dosyalarını kaldırır.
Yeni projeler için Google, SharedPreferences'ın yerine DataStore'u önerir. DataStore, coroutine ile eşzamansız çalışma, tür güvenliği (Proto DataStore) ve otomatik geçişler sağlar. SharedPreferences yalnızca minimum sürümü API 14'ün altında olan projeler için veya ek bağımlılıklar olmadan hızlı entegrasyon gerektiğinde seçilmelidir.
Veri şifreleme için AndroidX Security kütüphanesinden EncryptedSharedPreferences kullanın. AES-256 GCM kullanarak anahtarları ve değerleri otomatik olarak şifreler. Kurulum süreci minimumdur: getSharedPreferences, Android Keystore'dan bir ana anahtar belirterek EncryptedSharedPreferences.create ile değiştirilir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun