Room, Android'de SQLite ile çalışmak için bir kütüphanedir ve Jetpack'in bir parçasıdır. Ham SQLite üzerinde bir soyutlama katmanı sağlayarak tablo oluşturma, sorgu yürütme ve verileri Kotlin ve Java nesnelerine dönüştürme işlemlerini otomatikleştirir. Android Developers'a göre Room, SQL sorgularını derleme zamanında derleyerek sözdizimi doğruluğunu ve Entity ile tablolar arasındaki ilişkileri kontrol eder.
Önemli Noktalar
Room, SQLite için nesne-ilişkisel eşleme sağlayan bir Android Jetpack kalıcılık kütüphanesidir. Room, ham SQLite'in üç ana sorununu çözer: tablo oluşturmak için büyük miktarda kalıp kod yazma, derleme zamanında SQL sorgu doğrulamasının olmaması ve Cursor'ı manuel olarak nesnelere dönüştürme.
Kütüphane, derleme zamanında soyut RoomDatabase ve DAO sınıflarının uygulamasını oluşturan bir ek açıklama işlemcisi (kapt veya KSP) kullanır. Bu, SQL'deki sözdizimi hatalarının ve tür uyumsuzluklarının, uygulama Google Play'de yayınlandıktan sonra çalışma zamanında değil, uygulamayı çalıştırmadan önce keşfedilmesini sağlar.
Google I/O 2023'e göre Room, yerel verilerle çalışan Android uygulamalarının %68'inde kullanılmaktadır. Google tarafından tüm yeni projeler için önerilen, cihaz üzerinde veri depolama standardıdır — eski SQLiteOpenHelper ve ContentProvider yerine.
Sunucudan yerel veri önbellekleme, çevrimdışı mod veya karmaşık SQL sorguları çalıştırma yeteneği ile yapılandırılmış kullanıcı verilerini depolama gerektiren projelere Room'u entegre edin.
Room, Android Jetpack'in bir parçasıdır ve Google tarafından yerel verilerle çalışan tüm yeni projeler için resmi olarak önerilir. Realm veya ObjectBox'un aksine Room, yerel SQLite kullanır ve DB Browser'dan DataGrip'e kadar herhangi bir üçüncü taraf veritabanı aracıyla uyumluluğu garanti eder. Geliştiriciler, uygulamanın .db dosyasını açabilir ve doğrudan SQL sorguları çalıştırabilir, bu da geliştirme sırasında hata ayıklamayı ve veri analizini basitleştirir.
Entity, Room'un veritabanı tablosuna dönüştürdüğü, @Entity ile işaretlenmiş bir veri sınıfıdır. Sınıfın her alanı tablonun bir sütunu olur ve her örnek bir satır olur. Room, alanlara erişmek için yansıma kullanır, bu nedenle zorunlu bir tanımlayıcı için @PrimaryKey ek açıklaması gereklidir.
@Entity ek açıklaması, sınıfın bir tablo olduğunu Room'a bildirir. tableName parametresi, sınıf adından farklıysa tablo adını belirler. @PrimaryKey, autoGenerate = true ile otomatik oluşturma desteğiyle birincil anahtarı tanımlar.
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
@ColumnInfo(name = "full_name")
val name: String,
@Ignore
val tempData: String?
)
@ColumnInfo, Kotlin alan adından farklıysa tablodaki sütun adını belirtir. @Ignore bir alanı tablodan çıkarır — veritabanına kaydedilmez. @ForeignKey, silme veya güncelleme sırasında basamaklı işlemlerle tablolar arasındaki ilişkiler için yabancı anahtarları tanımlar.
Room, @Embedded ek açıklaması aracılığıyla iç içe nesneleri destekler. İç içe sınıfın alanları, ad çakışmalarını önlemek için bir önekle üst tablonun sütunlarına genişletilir. Örneğin, User'a gömülü city ve street alanlarına sahip bir Address sınıfı, users tablosunda address_city ve address_street sütunlarını oluşturarak basit değer nesneleri için ayrı tablolara olan ihtiyacı ortadan kaldırır.
Room yalnızca ilkel türleri ve bunların sarmalayıcılarını destekler. Listeleri, Date'i veya özel türleri depolamak için @TypeConverter kullanın — özel bir tür ile SQLite ilkel türü arasında dönüştürme yapan statik metotlar, örneğin List ve JSON dizesi arasında.
DAO (Veri Erişim Nesnesi), @Dao ile işaretlenmiş bir arayüz veya soyut sınıftır ve veri erişimi için metotlar içerir. Her metot bir SQL işlemiyle işaretlenir: @Insert, @Update, @Delete veya açık bir SQL sorgusu ile @Query.
@Query ek açıklaması, Room'un derleme zamanında sözdizimi doğruluğu ve sütun adlarının Entity alanlarıyla eşleşmesi için doğruladığı bir SQL dizesi alır. Room, :paramName sözdizimi aracılığıyla parametreleştirilmiş sorguları destekler.
@Dao
interface UserDao {
@Query("SELECT * FROM users WHERE id = :userId")
suspend fun getUserById(userId: Int): User?
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUser(user: User)
@Query("SELECT * FROM users ORDER BY name ASC")
fun getAllUsers(): Flow<List<User>>
}
@Insert, yinelenen kayıtları eklerken çakışmaları yönetmek için OnConflictStrategy seçeneklerini destekler. Dönüş türü olarak Flow, tablodaki her veri değişikliğinde tepkisel kullanıcı arayüzü güncellemeleri sağlar — abonelik her INSERT, UPDATE veya DELETE'te otomatik olarak yeniden başlar.
@Transaction ek açıklaması, tek bir işlem bloğu içinde birden çok işlemin atomik olarak yürütülmesini garanti eder. Room, yürütme sırasında veritabanını kilitleyerek birden çok iş parçacığından eşzamanlı erişim sırasında yarış koşullarını önler.
RoomDatabase, Entity ve DAO'yu tek bir veritabanı erişim noktasında birleştiren soyut bir sınıftır. Şema versiyonu ve Entity sınıflarının bir listesi ile Room.databaseBuilder aracılığıyla oluşturulur. Veritabanı örneği, birden çok bağlantıyı önlemek için tembel bir temsilci aracılığıyla tekil olarak oluşturulmalıdır.
Room'da taşıma, eski bir şema sürümünden yenisine geçiş için bir SQL betiğini tanımlayan Migration sınıfıdır. Şema değiştiğinde bir taşıma sağlanmazsa, Room bir IllegalStateException fırlatır. Bu, uygulama güncellenirken yanlışlıkla kullanıcı verisi kaybına karşı korur.
val migration_1_2 = object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE users ADD COLUMN age INTEGER NOT NULL DEFAULT 0")
}
}
val db = Room.databaseBuilder(
getApplication(),
AppDatabase::class.java,
"app_database"
).addMigrations(migration_1_2)
.build()
Geliştirme için fallbackToDestructiveMigration kullanabilirsiniz; bu, sürüm uyuşmazlığında eski veritabanını siler ve yenisini oluşturur. Bu mod yalnızca hata ayıklama içindir — üretim sürümleri uygun taşıma betiklerini içermelidir.
Veritabanı testi için Room, özel bir sınıf olan Room.inMemoryTestBuilder sağlar; bu, diske kaydetmeden bellekte bir veritabanı oluşturur. Her test tamamlandıktan sonra veritabanı otomatik olarak yok edilir ve test senaryolarının tamamen izole edilmesi sağlanır. android-arch-core-testing kütüphanesi ile birleştirildiğinde, geliştiriciler durumu manuel olarak temizlemeden veritabanı yaşam döngüsünü yönetebilir ve taşıma doğruluğunu doğrulayabilir.
Room performansı doğrudan sorgu yapısına ve indekslere bağlıdır. Yavaş sorguları analiz etmek için Room, enableQueryCallback bayrağını sağlar; bu, yürütme süresiyle birlikte tüm SQL sorgularını günlüğe kaydeder. Geliştiriciler bu günlüğü 100 milisaniyeden uzun süren sorguları bulmak ve @Entity'de @Index ek açıklaması aracılığıyla bileşik indeksler ekleyerek veya @Relation kullanarak alt sorguları doğrudan JOIN işlemlerine yeniden yazarak optimize etmek için kullanabilir.
Room ayrıca SQLCipher aracılığıyla veritabanı şifrelemeyi de destekler. net.zetetic:android-database-sqlcipher kütüphanesini eklemek ve standart olanın yerine SupportFactory kullanmak, DAO sorgularını veya Entity yapısını değiştirmeden diskteki tüm verilerin şeffaf şifrelenmesini sağlar. Bu, kullanıcıların kişisel verilerini işleyen uygulamalar için gereklidir ve GDPR ile kişisel verilerin korunmasına ilişkin Rusya Federal Kanunu 152-FZ'ye uygundur. Şifreleme parolası, root'lu cihazlarda araçlar aracılığıyla çıkarılmaya karşı korumak için Android Keystore'da saklanabilir.
Room, sürüm 2.1'den itibaren Kotlin Coroutines'i yerel olarak destekler. DAO metotları, ana iş parçacığını bloke etmeden arka plan iş parçacığında sorguları yürüten askıya alma işlevleri olabilir. Room, okuyucu ve yazıcı sorguları için Dispatchers.IO kullanarak dağıtıcıları otomatik olarak yönetir.
Tepkisel sorgular için Room bir Flow döndürür — etkilenen tablodaki her değişiklikte yeni bir değer yayan soğuk bir veri akışıdır. ViewModel, stateIn veya collect aracılığıyla Flow'a abone olur ve bağdaştırıcıyı manuel olarak bildirmeden otomatik kullanıcı arayüzü güncellemeleri sağlar.
Room ayrıca SQLite'dan sayfa sayfa veri yükleyen özel bir PagingSource uygulaması aracılığıyla Paging 3'ü de destekler. Bu, binlerce kayda sahip büyük listeler için verimlidir: Paging 3 yalnızca ekranda görünen satırları yükler ve veritabanı değişikliklerinde bunları otomatik olarak günceller.
Çevrimdışı erişim ve sonsuz kaydırma ile haber akışları, işlem günlükleri veya ürün listeleri görüntülemek için Room ile Paging 3'ü kullanın.
Sıkça Sorulan Sorular
Room, tablo oluşturma, Cursor'ı nesnelere dönüştürme ve derleme zamanında SQL doğrulamasını otomatikleştirir. SQLiteOpenHelper, şemanın manuel olarak yazılmasını, Cursor'ın işlenmesini gerektirir ve uygulamayı çalıştırmadan önce sorgu doğrulaması yapmaz, bu da hata riskini artırır.
Evet, bir Entity değiştirilirken (alan ekleme/kaldırma, tür değiştirme), bir taşıma gereklidir. Taşıma olmadan, Room başlangıçta IllegalStateException fırlatır. Geliştirme için fallbackToDestructiveMigration'ı etkinleştirebilirsiniz, ancak üretim sürümleri doğru taşıma betiklerini gerektirir.
Room, basamaklı işlemler için @ForeignKey ve iç içe nesneler için @Relation'ı destekler. Karmaşık JOIN sorguları için @Embedded ve @Relation aracılığıyla iç içe varlıklar içeren bir POJO döndüren @Query ile @Transaction ek açıklamasını kullanın.
Evet, Room Java ile tamamen uyumludur. Askıya alma işlevleri yerine LiveData veya RxJava Observable kullanın; Flow yerine LiveData kullanın. Java ile Room aynı ek açıklamaların tümünü destekler ancak eşzamansız işlemler için daha fazla kalıp kod gerektirir.
Room, Zetetic'in SQLCipher'ı aracılığıyla şifrelemeyi destekler. Room.databaseBuilder yerine, net.zetetic:android-database-sqlcipher kütüphanesinden SupportFactory kullanarak şifreleme parolasını iletin. Diskteki tüm veriler DAO sorgularına karşı şeffaf bir şekilde şifrelenir.
Ö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