Sorguların kullanıcı arayüzünü engellemesini önlemek için Room, ana iş parçacığında veritabanı erişimini desteklemez. Bu kısıtlama, DAO sorgularınızı eşzamansız yapmanız gerektiği anlamına gelir. Room kitaplığı, eşzamansız sorgu yürütme sağlamak için çeşitli çerçevelerle entegrasyonlar içerir.
DAO sorguları üç kategoriye ayrılır:
- Veritabanına veri ekleyen, verileri güncelleyen veya silen tek seferlik yazma sorguları.
- Verileri veritabanınızdan yalnızca bir kez okuyup o sırada veritabanının anlık görüntüsünü içeren bir sonuç döndüren tek seferlik okuma sorguları.
- Temel veritabanı tabloları her değiştiğinde veritabanınızdan veri okuyan ve bu değişiklikleri yansıtmak için yeni değerler yayan gözlemlenebilir okuma sorguları.
Dil ve çerçeve seçenekleri
Room, belirli dil özellikleri ve kitaplıklarla birlikte çalışabilirlik için entegrasyon desteği sağlar. Aşağıdaki tabloda, sorgu türüne ve çerçeveye göre geçerli olan dönüş türleri gösterilmektedir:
| Sorgu türü | Kotlin dil özellikleri (yerel) | RxJava | Guava | Jetpack Lifecycle* |
|---|---|---|---|---|
| Tek seferlik yazma | Eş yordamlar (suspend) |
Single<T>, Maybe<T>,
Completable |
ListenableFuture<T> |
Yok |
| Tek seferde okuma | Eş yordamlar (suspend) |
Single<T>, Maybe<T> |
ListenableFuture<T> |
Yok |
| Gözlemlenebilir okuma | Flow<T> |
Flowable<T>, Publisher<T>,
Observable<T> |
Yok | LiveData<T> |
Bu kılavuzda, DAO'larınızda eşzamansız sorgular uygulamak için bu entegrasyonları kullanmanın üç yolu gösterilmektedir.
Flow ve eş yordamlarla Kotlin
Kotlin, üçüncü taraf çerçeveleri olmadan eşzamansız sorgular yazmanıza olanak tanıyan yerleşik dil özellikleri sunar:
- Room, gözlemlenebilir sorgular yazmak için Kotlin'in Flow özelliğini doğrudan destekler.
- Room, tek seferlik DAO sorgularınızı Kotlin coroutines ile eşzamansız hale getirmek için
suspendanahtar kelimesini gerektirir.
Coroutines ve Flow desteği doğrudan temel Room çalışma zamanına yerleştirildiğinden ek yapılar gerekmez.
Kotlin ve Java için RxJava
Room 3.0, RxJava 3 dönüş türlerini destekler. RxJava dönüş türlerini kullanmak için RxJava dönüş türü dönüştürücülerini veritabanınızda veya DAO'nuzda kaydetmeniz gerekir:
- Derleme yapılandırmanıza
androidx.room3:room3-rxjava3yapıtını ekleyin. @Databaseveya@Daobeyanınıza@DaoReturnTypeConverters(RxDaoReturnTypeConverters::class)ile açıklama ekleyin.
Room, aşağıdaki RxJava 3 dönüş türlerini destekler:
- Tek görevli sorgular:
Completable,Single<T>, veMaybe<T> - Gözlemlenebilir sorgular:
Publisher<T>,Flowable<T>, veObservable<T>
LiveData ve Guava
Room 3.0, dönüştürücüler kullanılarak LiveData ve Guava ListenableFuture dönüş türlerini destekler:
- LiveData:
androidx.room3:room3-livedatayapısını ekleyin ve veritabanınızı veya DAO'nuzu@DaoReturnTypeConverters(LiveDataDaoReturnTypeConverter::class)ile açıklama ekleyin. - Guava:
androidx.room3:room3-guavayapısını ekleyin ve veritabanınıza veya DAO'nuza@DaoReturnTypeConverters(GuavaDaoReturnTypeConverter::class)ile açıklama ekleyin.
Eşzamansız tek seferlik sorgular yazma
Tek seferlik sorgular, yalnızca bir kez çalıştırılan ve yürütme sırasında verilerin anlık görüntüsünü alan veritabanı işlemleridir. Aşağıda, eşzamansız tek seferlik sorgulara ilişkin bazı örnekler verilmiştir:
@Dao interface UserDao { @Query("SELECT * FROM user WHERE id = :id") suspend fun loadUserById(id: Int): User @Query("SELECT * from user WHERE region IN (:regions)") suspend fun loadUsersByRegion(regions: List<String>): List<User> }
Gözlemlenebilir sorgular yazma
Gözlemlenebilir sorgular, referans verilen tablolar her değiştiğinde yeni değerler yayan okuma işlemleridir. Örneğin, bu davranışı kullanarak veritabanı değiştikçe görüntülenen öğe listesini güncel tutabilirsiniz. Aşağıda, gözlemlenebilir sorgulara ilişkin bazı örnekler verilmiştir:
@Dao interface ObservableUserDao { @Query("SELECT * FROM user WHERE id = :id") fun loadUserById(id: Int): Flow<User> @Query("SELECT * from user WHERE region IN (:regions)") fun loadUsersByRegion(regions: List<String>): Flow<List<User>> }
Veritabanı geçersiz kılmayı manuel olarak izleme
Gözlemlenebilir veritabanı işlemlerini manuel olarak oluşturmanız gerektiğinde InvalidationTracker'ın createFlow API'sini kullanabilirsiniz. Bu API, belirli tablolarda yapılan değişiklikleri izleyen bir Flow oluşturmanıza ve bu tablolar her değiştiğinde bildirim göndermenize olanak tanır.
fun getArtistTours(db: RoomDatabase, from: Date, to: Date): Flow<Map<Artist, TourState>> { return db.invalidationTracker.createFlow("Artist").map { _ -> val artists = artistsDao.getAllArtists() val tours = tourService.fetchStates(artists.map { it.id }) associateTours(artists, tours, from, to) } }
Varsayılan olarak, döndürülen Flow, akışı başlatmak için tüm kayıtlı tabloları içeren bir başlangıç değeri yayar. emitInitialState parametresini false olarak ayarlayarak bu davranışı devre dışı bırakabilirsiniz.
Özel DAO dönüş türü dönüştürücüleri
Room veya uzantı kitaplıkları tarafından doğrudan desteklenmeyen türler için ek dönüş türlerini desteklemek üzere özel DAO dönüş türü dönüştürücüleri tanımlayabilirsiniz. Bir DAO işlevinin sonucunu özel türünüze dönüştürmek için bir dönüştürücü işlevi @DaoReturnTypeConverter ile açıklama ekleyin.
Örneğin, androidx.tracing kullanarak sorgu yürütme etrafına izleme bölümleri ekleyen bir dönüştürücü tanımlayabilirsiniz. Bu sayede, yürütmeyi özel bir TracedQuery türüne sarmalayarak performansa duyarlı sorguları izleyebilirsiniz:
class TracedQuery<T>(val result: T) object TracingDaoReturnTypeConverter { @DaoReturnTypeConverter([OperationType.READ]) suspend fun <T> convert( rawQuery: RoomRawQuery, executeAndConvert: suspend () -> T ): TracedQuery<T> { val result = trace("TracedQuery: ${rawQuery.sql}") { executeAndConvert() } return TracedQuery(result) } }
Dönüştürücüyü kullanmak için veritabanınıza veya DAO'nuza
@DaoReturnTypeConverters ile açıklama ekleyin:
@Dao @DaoReturnTypeConverters(TracingDaoReturnTypeConverter::class) interface MusicDao { @Query("SELECT * FROM Song") suspend fun getAllSongs(): TracedQuery<List<Song>> }
DAO dönüş türü dönüştürücüsünün başlatılmasını kontrol etme
Normalde Room, DAO dönüş türü dönüştürücülerinin oluşturulmasını yönetir.
Ancak dönüştürücü sınıflarınıza ek bağımlılıklar iletmeniz gerekiyorsa uygulamanız bunların başlatılmasını doğrudan kontrol etmelidir. Bu durumda dönüştürücü sınıfınıza @ProvidedDaoReturnTypeConverter ekleyin:
@ProvidedDaoReturnTypeConverter class TracingDaoReturnTypeConverter(val tracer: Tracer) { @DaoReturnTypeConverter([OperationType.READ]) suspend fun <T> convert( rawQuery: RoomRawQuery, executeAndConvert: suspend () -> T ): TracedQuery<T> { val result = tracer.trace("TracedQuery: ${rawQuery.sql}") { executeAndConvert() } return TracedQuery(result) } }
Ardından, dönüştürücü sınıfınızı @DaoReturnTypeConverters içinde tanımlamanın yanı sıra RoomDatabase.Builder.addDaoReturnTypeConverter işlevini kullanarak dönüştürücü sınıfınızın bir örneğini RoomDatabase oluşturucuya iletin:
val db = Room.databaseBuilder<MyDatabase>(applicationContext, "database-name") .addDaoReturnTypeConverter(TracingDaoReturnTypeConverter(myLoggerInstance)) .build()
Dönüştürücü işleviyle ilgili şartlar
@DaoReturnTypeConverter işlevinin çeşitli koşulları karşılaması gerekir:
- Son bağımsız değişkeni olarak işlevsel bir parametreye sahip olmalıdır. Bu parametre genellikle
executeAndConvertolarak adlandırılır. Bu parametre, sorguyu yürütmek ve sonucu ayrıştırmak için Room'un oluşturduğu birsuspendlambda'dır.- Dönüştürücünün sorguyu dönüştürmesi gerekiyorsa (ör. Sayfalama), lambda
RoomRawQueryparametresini alabilir.
- Dönüştürücünün sorguyu dönüştürmesi gerekiyorsa (ör. Sayfalama), lambda
- Lambda'dan önce isteğe bağlı olarak aşağıdaki parametreleri kabul edebilir:
db: RoomDatabase: Veritabanı örneğine erişir. Bu, coroutine kapsamını elde etmek veya ek işlemler gerçekleştirmek için yararlıdır.tableNames: Array<String>veyaList<String>: Sorgu tarafından erişilen tabloların adlarını sağlar. Bu, gözlemlenebilir türler için yararlıdır.rawQuery: RoomRawQuery: Sorgunun çalışma zamanı örneğini sağlar.inTransaction: Boolean: Sorgunun bir işlem içinde yürütülüp yürütülmediğini gösterir.