Oda, temel ve kutulu türler arasında dönüştürme işlevi sunar ancak varlıklar arasında nesne referanslarına izin vermez. Bu belgede, tür dönüştürücülerin nasıl kullanılacağı ve Room'un nesne referanslarını neden desteklemediği açıklanmaktadır.
Tür dönüştürücüleri kullan
Bazen uygulamanızın özel bir veri türünü tek bir veritabanı sütununda depolaması gerekir. Özel türleri, tür dönüştürücüler sağlayarak desteklersiniz. Bu yöntemler, Room'a özel türlerin Oda'nın sürdürebileceği bilinen türlere nasıl dönüştürüleceğini bildiren yöntemlerdir. Tür dönüştürücüleri, @TypeConverter
ek açıklamasını kullanarak tanımlarsınız.
Oda veritabanınızda Date
örneklerini tutmanız gerektiğini varsayalım. Oda, Date
nesnelerini nasıl koruyacağını bilemez. Bu nedenle, tür dönüştürücüleri tanımlamanız gerekir:
Kotlin
class Converters { @TypeConverter fun fromTimestamp(value: Long?): Date? { return value?.let { Date(it) } } @TypeConverter fun dateToTimestamp(date: Date?): Long? { return date?.time?.toLong() } }
Java
public class Converters { @TypeConverter public static Date fromTimestamp(Long value) { return value == null ? null : new Date(value); } @TypeConverter public static Long dateToTimestamp(Date date) { return date == null ? null : date.getTime(); } }
Bu örnekte iki tür dönüştürücü yöntemi tanımlanmaktadır: bir Date
nesnesini Long
nesnesine dönüştüren bir yöntem ve Long
nesnesinden Date
nesnesine ters dönüştürme işlemi gerçekleştiren bir yöntem. Room, Long
nesnelerini nasıl koruyacağını bildiğinden, Date
nesnelerini saklamak için bu dönüştürücüleri kullanabilir.
Ardından, Oda'nın tanımladığınız dönüştürücü sınıfı hakkında bilgi sahibi olması için @TypeConverters
ek açıklamasını AppDatabase
sınıfına eklersiniz:
Kotlin
@Database(entities = [User::class], version = 1) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
Java
@Database(entities = {User.class}, version = 1) @TypeConverters({Converters.class}) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
Bu tür dönüştürücüler tanımlandığında, özel türünüzü varlıklarınızda ve DAO'larınızda temel türleri kullandığınız gibi kullanabilirsiniz:
Kotlin
@Entity data class User(private val birthday: Date?) @Dao interface UserDao { @Query("SELECT * FROM user WHERE birthday = :targetDate") fun findUsersBornOnDate(targetDate: Date): List<User> }
Java
@Entity public class User { private Date birthday; } @Dao public interface UserDao { @Query("SELECT * FROM user WHERE birthday = :targetDate") List<User> findUsersBornOnDate(Date targetDate); }
Bu örnekte, AppDatabase
öğesine @TypeConverters
ek açıklaması eklediğiniz için Room tanımlı tür dönüştürücüyü her yerde kullanabilir. Ancak @Entity
veya @Dao
sınıflarınıza @TypeConverters
ile ek açıklama ekleyerek tür dönüştürücüleri de belirli varlıklara veya DAO'lara dahil edebilirsiniz.
Kontrol türü dönüştürücü başlatma
Normalde Room, sizin için tür dönüştürücülerin örneklendirmesini işler. Ancak, bazen tür dönüştürücü sınıflarınıza ek bağımlılıklar aktarmanız gerekebilir. Bu da uygulamanızın, tür dönüştürücülerinizin başlatılmasını doğrudan kontrol etmesi gerektiği anlamına gelir. Bu durumda, dönüştürücü sınıfınıza @ProvidedTypeConverter
ek açıklaması ekleyin:
Kotlin
@ProvidedTypeConverter class ExampleConverter { @TypeConverter fun StringToExample(string: String?): ExampleType? { ... } @TypeConverter fun ExampleToString(example: ExampleType?): String? { ... } }
Java
@ProvidedTypeConverter public class ExampleConverter { @TypeConverter public Example StringToExample(String string) { ... } @TypeConverter public String ExampleToString(Example example) { ... } }
Ardından, dönüştürücü sınıfınızı @TypeConverters
içinde belirtmenin yanı sıra RoomDatabase.Builder.addTypeConverter()
yöntemini kullanarak dönüştürücü sınıfınızın bir örneğini RoomDatabase
oluşturucuya geçirin:
Kotlin
val db = Room.databaseBuilder(...) .addTypeConverter(exampleConverterInstance) .build()
Java
AppDatabase db = Room.databaseBuilder(...) .addTypeConverter(exampleConverterInstance) .build();
Room'un nesne referanslarına neden izin vermediğini anlama
Temel çıkarım: Oda, varlık sınıfları arasında nesne referanslarına izin vermez. Bunun yerine, uygulamanızın ihtiyaç duyduğu verileri açıkça istemelisiniz.
Bir veritabanından ilgili nesne modeliyle ilişkilerin eşlenmesi yaygın bir uygulamadır ve sunucu tarafında çok iyi sonuç verir. Program, alanları kendilerine erişildiğinde yüklese bile sunucu yine de iyi performans gösterir.
Bununla birlikte, istemci tarafında bu tür geç yükleme, genellikle kullanıcı arayüzü iş parçacığında gerçekleştiği ve kullanıcı arayüzü iş parçacığındaki diskteki bilgilerin sorgulanması önemli performans sorunları oluşturduğu için uygun değildir. UI iş parçacığının, bir etkinliğin güncellenmiş düzenini hesaplamak ve çizmek için yaklaşık 16 ms'si vardır. Bu nedenle, bir sorgu yalnızca 5 ms Paralel olarak çalışan ayrı bir işlem varsa veya cihaz diski yoğun şekilde kullanan başka görevler çalıştırıyorsa sorgunun tamamlanması daha da uzun sürebilir. Ancak geç yükleme kullanmazsanız uygulamanız gerekenden daha fazla veri getirir ve bu da bellek tüketimi sorunlarına yol açar.
Nesne ilişki eşlemelerinde, uygulamalarının kullanım alanlarına en uygun olanı yapabilmeleri için genellikle bu kararı geliştiricilere bırakırlar. Geliştiriciler genellikle modeli uygulamaları ve kullanıcı arayüzü arasında paylaşmaya karar verirler. Ancak bu çözüm iyi ölçeklenemez. Ancak kullanıcı arayüzü zamanla değiştikçe paylaşılan model geliştiricilerin tahmin etmesi ve hata ayıklaması zor sorunlar yaratır.
Örneğin, her kitap bir Author
nesnesine sahip olacak şekilde Book
nesnelerinin listesini yükleyen bir kullanıcı arayüzünü düşünün. Başlangıçta sorgularınızı Book
örneklerinin yazarı almasını sağlamak için geç yükleme özelliğini kullanacak şekilde tasarlayabilirsiniz. author
alanı ilk kez alındığında veritabanı sorgulanır. Bir süre sonra, uygulamanızın
kullanıcı arayüzünde yazar adını da görüntülemeniz gerektiğini fark edersiniz. Aşağıdaki kod snippet'inde gösterildiği gibi bu ada yeterince kolay erişebilirsiniz:
Kotlin
authorNameTextView.text = book.author.name
Java
authorNameTextView.setText(book.getAuthor().getName());
Ancak masum görünen bu değişiklik, Author
tablosunun ana iş parçacığında sorgulanmasına neden olur.
Yazar bilgilerini önceden sorguladığınızda, artık ihtiyaç duymadığınız verilerin yüklenme biçimini değiştirmek zorlaşır. Örneğin, uygulamanızın kullanıcı arayüzünün Author
bilgilerini artık görüntülemesi gerekmiyorsa uygulamanız artık göstermediği verileri etkili bir şekilde yükleyerek değerli bellek alanı boşa harcar. Author
sınıfı Books
gibi başka bir tabloya referans veriyorsa uygulamanızın verimliliği daha da düşer.
Oda özelliğini kullanarak aynı anda birden çok varlığa referans vermek için bunun yerine her varlığı içeren bir POJO oluşturur ve ilgili tabloları birleştiren bir sorgu yazarsınız. Bu iyi yapılandırılmış model, Room'un güçlü sorgu doğrulama özellikleriyle bir araya geldiğinde uygulamanızın veri yüklerken daha az kaynak tüketmesini sağlayarak uygulamanızın performansını ve kullanıcı deneyimini iyileştirir.