Android Kotlin Hakkında Temel Bilgiler 06.1: Room veritabanı oluşturma

Bu codelab, Android Kotlin Hakkında Temel Bilgiler kursunun bir parçasıdır. Bu kurstan en iyi şekilde yararlanmak için codelab'leri sırayla tamamlamanızı öneririz. Kursla ilgili tüm codelab'ler Android Kotlin Hakkında Temel Bilgiler codelab'leri açılış sayfasında listelenir.

Giriş

Çoğu uygulamada, kullanıcı uygulamayı kapattıktan sonra bile saklanması gereken veriler bulunur. Örneğin, uygulama bir oynatma listesini, oyun öğelerinin envanterini, gider ve gelir kayıtlarını, takımyıldızlar kataloğunu veya zaman içindeki uyku verilerini saklayabilir. Genellikle kalıcı verileri depolamak için bir veritabanı kullanırsınız.

Room, Android Jetpack'in bir parçası olan bir veritabanı kitaplığıdır. Room, veritabanı oluşturma ve yapılandırma işlemlerinin çoğunu halleder ve uygulamanızın normal işlev çağrılarını kullanarak veritabanıyla etkileşim kurmasını sağlar. Room, arka planda SQLite veritabanının üzerinde bir soyutlama katmanıdır. Room'ın terminolojisi ve daha karmaşık sorgular için sorgu söz dizimi, SQLite modelini takip eder.

Aşağıdaki resimde, Room veritabanının bu kursta önerilen genel mimariye nasıl uyduğu gösterilmektedir.

Bilmeniz gerekenler

Aşağıdaki konular hakkında bilgi sahibi olmanız gerekir:

  • Android uygulaması için temel bir kullanıcı arayüzü (UI) oluşturma
  • Etkinlikleri, parçaları ve görünümleri kullanma
  • Parçalar arasında gezinme ve parçalar arasında veri aktarmak için Safe Args'ı (bir Gradle eklentisi) kullanma.
  • Modeller, görünüm modeli fabrikaları ve LiveData ile gözlemcileri. Bu Mimari Bileşenler konuları, bu kurstaki önceki bir codelab'de ele alınmıştır.
  • SQL veritabanları ve SQLite dili hakkında temel bilgiler. Hızlı bir genel bakış veya hatırlatma için SQLite Primer'ı inceleyin.

Neler öğreneceksiniz?

  • Verileri kalıcı hale getirmek için Roomveritabanı oluşturma ve veritabanıyla etkileşimde bulunma
  • Veritabanındaki bir tabloyu tanımlayan veri sınıfı oluşturma
  • Kotlin işlevlerini SQL sorgularıyla eşlemek için veri erişim nesnesi (DAO) nasıl kullanılır?
  • Veritabanınızın çalışıp çalışmadığını test etme

Yapacaklarınız

  • Gece uyku verileri için arayüz içeren bir Room veritabanı oluşturun.
  • Veritabanını, sağlanan testleri kullanarak test edin.

Bu codelab'de, uyku kalitesini izleyen bir uygulamanın veritabanı bölümünü oluşturacaksınız. Uygulama, uyku verilerini zaman içinde saklamak için bir veritabanı kullanır.

Uygulama, aşağıdaki şekilde gösterildiği gibi parçalarla temsil edilen iki ekrana sahiptir.

Solda gösterilen ilk ekranda izlemeyi başlatma ve durdurma düğmeleri bulunur. Ekranda kullanıcının tüm uyku verileri gösterilir. Temizle düğmesi, uygulamanın kullanıcı için topladığı tüm verileri kalıcı olarak siler.

Sağda gösterilen ikinci ekranda uyku kalitesi derecesi seçilir. Uygulamada puan sayısal olarak gösterilir. Uygulama, geliştirme amacıyla hem yüz simgelerini hem de bunların sayısal karşılıklarını gösterir.

Kullanıcının akışı şu şekildedir:

  • Kullanıcı uygulamayı açar ve uyku takibi ekranı gösterilir.
  • Kullanıcı, Başlat düğmesine dokunur. Bu işlev, başlangıç zamanını kaydeder ve görüntüler. Başlat düğmesi devre dışı, Durdur düğmesi ise etkin olur.
  • Kullanıcı, Durdur düğmesine dokunur. Bu işlem, bitiş zamanını kaydeder ve uyku kalitesi ekranını açar.
  • Kullanıcı, uyku kalitesi simgesi seçer. Ekran kapanır ve takip ekranında uyku bitiş saati ile uyku kalitesi gösterilir. Durdur düğmesi devre dışı, Başlat düğmesi ise etkin olur. Uygulama başka bir geceye hazır.
  • Veritabanında veri olduğunda Temizle düğmesi etkinleştirilir. Kullanıcı Temizle düğmesine dokunduğunda tüm verileri geri dönüşü olmayacak şekilde silinir. "Emin misiniz?" mesajı gösterilmez.

Bu uygulama, tam mimari bağlamında aşağıda gösterildiği gibi basitleştirilmiş bir mimari kullanır. Uygulama yalnızca aşağıdaki bileşenleri kullanır:

  • Kullanıcı arayüzü denetleyicisi
  • Modeli ve LiveData görüntüleme
  • Room veritabanı

1. adım: Başlangıç uygulamasını indirip çalıştırın

  1. GitHub'dan TrackMySleepQuality-Starter uygulamasını indirin.
  2. Uygulamayı oluşturup çalıştırın. Uygulama, SleepTrackerFragment parçası için kullanıcı arayüzünü gösteriyor ancak veri göstermiyor. Düğmeler dokunmaya yanıt vermiyor.

2. adım: Başlangıç uygulamasını inceleyin

  1. Gradle dosyalarına göz atın:
  • Proje Gradle dosyası
    Proje düzeyindeki build.gradle dosyasında, kitaplık sürümlerini belirten değişkenlere dikkat edin. Başlangıç uygulamasında kullanılan sürümler birlikte ve bu uygulamayla iyi çalışır. Bu codelab'i tamamladığınızda Android Studio, bazı sürümleri güncellemenizi isteyebilir. Güncelleme yapmak veya uygulamadaki sürümleri kullanmaya devam etmek sizin tercihinizdir. "Garip" derleme hatalarıyla karşılaşırsanız nihai çözüm uygulamasının kullandığı kitaplık sürümlerinin kombinasyonunu kullanmayı deneyin.
  • Modül Gradle dosyası. Room dahil olmak üzere tüm Android Jetpack kitaplıkları ve coroutines'e ait bağımlılıkları inceleyin.
  1. Paketlere ve kullanıcı arayüzüne göz atın. Uygulama, işlevselliğe göre yapılandırılmıştır. Paket, bu bir dizi kod laboratuvarı boyunca kod ekleyeceğiniz yer tutucu dosyalar içerir.
  • Room veritabanıyla ilgili tüm kodlar için database paketi.
  • sleepquality ve sleeptracker paketleri her ekran için parçayı, görünüm modelini ve görünüm modeli fabrikasını içerir.
  1. Uyku kalitesi verilerinin gösterilmesine yardımcı olacak işlevleri içeren Util.kt dosyasına göz atın. Bazı kodlar, daha sonra oluşturacağınız bir görünüm modeline başvurduğu için yorum satırı olarak işaretlenir.
  2. androidTest klasörüne (SleepDatabaseTest.kt) göz atın. Veritabanının beklendiği gibi çalıştığını doğrulamak için bu testi kullanacaksınız.

Android'de veriler, veri sınıflarında temsil edilir. Verilere, işlev çağrıları kullanılarak erişilir ve veriler değiştirilir. Ancak veritabanı dünyasında varlıklara ve sorgulara ihtiyacınız vardır.

  • Varlık, veritabanında depolanacak bir nesneyi veya kavramı ve özelliklerini temsil eder. Bir öğe sınıfı tabloyu tanımlar ve bu sınıfın her örneği tablodaki bir satırı temsil eder. Her özellik bir sütunu tanımlar. Uygulamanızda, uykuyla ilgili bilgiler tutulur.
  • Sorgu, bir veri tabanı tablosundan veya tablo kombinasyonundan veri ya da bilgi isteği ya da veriler üzerinde bir işlem gerçekleştirme isteğidir. Yaygın sorgular, varlıkları alma, ekleme ve güncelleme ile ilgilidir. Örneğin, kayıtlı tüm uyku gecelerini başlangıç zamanına göre sıralayarak sorgulayabilirsiniz.

Room, Kotlin veri sınıflarından SQLite tablolarında depolanabilen varlıklara ve işlev bildirimlerinden SQL sorgularına geçiş yapmanız için tüm zorlu işlemleri sizin yerinize yapar.

Her bir öğeyi açıklama eklenmiş bir veri sınıfı, etkileşimleri ise açıklama eklenmiş bir arayüz (veri erişim nesnesi (DAO)) olarak tanımlamanız gerekir. Room, veritabanında tablolar ve veritabanında işlem yapan sorgular oluşturmak için bu açıklama eklenmiş sınıfları kullanır.

1. adım: SleepNight öğesini oluşturun

Bu görevde, bir gecelik uykuyu açıklama eklenmiş bir veri sınıfı olarak tanımlayacaksınız.

Bir gecelik uyku için başlangıç zamanını, bitiş zamanını ve kalite derecesini kaydetmeniz gerekir.

Ayrıca geceyi benzersiz şekilde tanımlamak için bir kimliğe ihtiyacınız vardır.

  1. database paketinde SleepNight.kt dosyasını bulup açın.
  2. Kimlik, başlangıç zamanı (milisaniye cinsinden), bitiş zamanı (milisaniye cinsinden) ve sayısal uyku kalitesi derecelendirmesi için parametreler içeren SleepNight veri sınıfını oluşturun.
  • sleepQuality değerini başlatmanız gerekir. Bu nedenle, kalite verisi toplanmadığını belirtmek için -1 olarak ayarlayın.
  • Ayrıca bitiş zamanını da başlatmanız gerekir. Henüz bitiş saati kaydedilmediğini belirtmek için başlangıç saatine ayarlayın.
data class SleepNight(
       var nightId: Long = 0L,
       val startTimeMilli: Long = System.currentTimeMillis(),
       var endTimeMilli: Long = startTimeMilli,
       var sleepQuality: Int = -1
)
  1. Sınıf bildiriminden önce veri sınıfını @Entity ile açıklama ekleyin. Tabloyu daily_sleep_quality_table olarak adlandırın. tableName bağımsız değişkeni isteğe bağlıdır ancak önerilir. Diğer bağımsız değişkenleri dokümanlarda arayabilirsiniz.

    İstenirse Entity ve diğer tüm ek açıklamaları androidx kitaplığından içe aktarın.
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(...)
  1. nightId özelliğini birincil anahtar olarak tanımlamak için nightId özelliğine @PrimaryKey ekleyin. autoGenerate parametresini true olarak ayarlayın. Böylece Room, her bir öğe için kimlik oluşturur. Bu, her gece için kimliğin benzersiz olmasını sağlar.
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,...
  1. Kalan özellikleri @ColumnInfo ile açıklama ekleyin. Aşağıda gösterildiği gibi parametreleri kullanarak mülk adlarını özelleştirin.
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(
       @PrimaryKey(autoGenerate = true)
       var nightId: Long = 0L,

       @ColumnInfo(name = "start_time_milli")
       val startTimeMilli: Long = System.currentTimeMillis(),

       @ColumnInfo(name = "end_time_milli")
       var endTimeMilli: Long = startTimeMilli,

       @ColumnInfo(name = "quality_rating")
       var sleepQuality: Int = -1
)
  1. Kodunuzu oluşturup çalıştırarak hatasız olduğundan emin olun.

Bu görevde bir veri erişim nesnesi (DAO) tanımlarsınız. Android'de DAO, veritabanına ekleme, silme ve güncelleme için kolaylık sağlayan yöntemler sunar.

Room veritabanı kullandığınızda kodunuzda Kotlin işlevlerini tanımlayıp çağırarak veritabanını sorgularsınız. Bu Kotlin işlevleri, SQL sorgularıyla eşlenir. Bu eşlemeleri, ek açıklamaları kullanarak bir DAO'da tanımlarsınız ve Room gerekli kodu oluşturur.

DAO'yu, veritabanınıza erişmek için özel bir arayüz tanımlama olarak düşünebilirsiniz.

Room kitaplığı, yaygın veritabanı işlemleri için @Insert, @Delete ve @Update gibi kolaylık sağlayan ek açıklamalar sunar. Diğer her şey için @Query ek açıklaması kullanılır. SQLite tarafından desteklenen herhangi bir sorguyu yazabilirsiniz.

Ek olarak, Android Studio'da sorgularınızı oluştururken derleyici, SQL sorgularınızda söz dizimi hataları olup olmadığını kontrol eder.

Uyku gecelerinin uyku izleyici veritabanı için aşağıdakileri yapabilmeniz gerekir:

  • Yeni geceler ekleyin.
  • Bitiş zamanını ve kalite derecelendirmesini güncellemek için mevcut bir geceyi güncelleyin.
  • Anahtarına göre belirli bir geceyi alın.
  • Tüm geceleri alın. Böylece bunları gösterebilirsiniz.
  • En son geceyi alın.
  • Veritabanındaki tüm girişleri silin.

1. adım: SleepDatabase DAO'yu oluşturun

  1. database paketinde SleepDatabaseDao.kt öğesini açın.
  2. interface SleepDatabaseDao ifadesinin @Dao ile açıklama eklendiğini unutmayın. Tüm DAO'lar @Dao anahtar kelimesiyle açıklama eklenmelidir.
@Dao
interface SleepDatabaseDao {}
  1. Arayüzün gövdesine bir @Insert ek açıklaması ekleyin. @Insert öğesinin altına, bağımsız değişken olarak Entity sınıfının bir örneğini SleepNight alan bir insert() işlevi ekleyin.

    Hepsi bu kadar. Room, SleepNight öğesini veritabanına eklemek için gereken tüm kodu oluşturur. Kotlin kodunuzdan insert() işlevini çağırdığınızda Room, varlığı veritabanına eklemek için bir SQL sorgusu yürütür. (Not: İşlevi istediğiniz gibi adlandırabilirsiniz.)
@Insert
fun insert(night: SleepNight)
  1. Bir SleepNight için update() işlevine sahip bir @Update ek açıklaması ekleyin. Güncellenen varlık, iletilen varlıkla aynı anahtara sahip olan varlıktır. Varlığın diğer özelliklerinin bir kısmını veya tamamını güncelleyebilirsiniz.
@Update
fun update(night: SleepNight)

Kalan işlevler için kolaylık sağlayan bir ek açıklama yoktur. Bu nedenle, @Query ek açıklamasını kullanmanız ve SQLite sorguları sağlamanız gerekir.

  1. Long key bağımsız değişkenini alan ve null değer atanabilir SleepNight döndüren bir get() işleviyle @Query ek açıklaması ekleyin. Eksik parametreyle ilgili bir hata görürsünüz.
@Query
fun get(key: Long): SleepNight?
  1. Sorgu, ek açıklamaya dize parametresi olarak sağlanır. @Query öğesine parametre ekleyin. Bunu SQLite sorgusu olan bir String yapın.
  • daily_sleep_quality_table
  • WHERE, nightId, :key bağımsız değişkeniyle eşleşiyor.

    :key simgesine dikkat edin. İşlevdeki bağımsız değişkenlere referans vermek için sorguda iki nokta üst üste gösterimini kullanırsınız.
("SELECT * from daily_sleep_quality_table WHERE nightId = :key")
  1. @Query işlevi ve SQLite sorgusu içeren başka bir @Query ekleyerek daily_sleep_quality_table'deki her şeyi DELETE.clear() Bu sorgu, tablonun kendisini silmez.

    @Delete notu bir öğeyi siler. Silinecek gecelerin listesini sağlamak için @Delete notunu kullanabilirsiniz. Dezavantajı, tablonun içeriğini getirmeniz veya bilmeniz gerekmesidir. @Delete notu, belirli girişleri silmek için idealdir ancak bir tablodaki tüm girişleri temizlemek için verimli değildir.
@Query("DELETE FROM daily_sleep_quality_table")
fun clear()
  1. getTonight() işleviyle @Query ekleyin. İşlevin tablonun boş olduğu durumu işleyebilmesi için getTonight() tarafından döndürülen SleepNight değerini null yapılabilir hale getirin. (Tablo başlangıçta ve veriler temizlendikten sonra boştur.)

    Veritabanından "bu gece"yi almak için nightId değerine göre azalan sırada sıralanmış sonuç listesinin ilk öğesini döndüren bir SQLite sorgusu yazın. Yalnızca bir öğe döndürmek için LIMIT 1 kullanın.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC LIMIT 1")
fun getTonight(): SleepNight?
  1. @Query işleviyle getAllNights() ekleme:
  • SQLite sorgusunun, daily_sleep_quality_table tablosundaki tüm sütunları azalan düzende döndürmesini sağlayın.
  • getAllNights(), SleepNight varlıklarının listesini LiveData olarak döndürsün. Room, bu LiveData öğesini sizin için güncel tutar. Bu nedenle, verileri yalnızca bir kez açıkça almanız gerekir.
  • LiveData dosyasını androidx.lifecycle.LiveData konumundan içe aktarmanız gerekebilir.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC")
fun getAllNights(): LiveData<List<SleepNight>>
  1. Görünür bir değişiklik olmasa da uygulamanızda hata olmadığından emin olmak için uygulamayı çalıştırın.

Bu görevde, önceki görevde oluşturduğunuz Entity ve DAO'yu kullanan bir Room veritabanı oluşturursunuz.

@Database ile açıklama eklenmiş bir soyut veritabanı tutucu sınıfı oluşturmanız gerekir. Bu sınıfta, veritabanı yoksa veritabanının bir örneğini oluşturan, veritabanı varsa mevcut veritabanına referans döndüren bir yöntem bulunur.

Room veritabanı edinmek biraz karmaşık bir süreçtir. Bu nedenle, kodla çalışmaya başlamadan önce genel süreci aşağıda bulabilirsiniz:

  • public abstract sınıfı oluşturun.extends RoomDatabase Bu sınıf, veritabanı sahibi olarak hareket eder. Room, sizin için uygulamayı oluşturduğundan sınıf soyuttur.
  • Sınıfa @Database ile not ekleyin. Bağımsız değişkenlerde, veritabanı için varlıkları bildirin ve sürüm numarasını ayarlayın.
  • companion nesnesinin içinde SleepDatabaseDao döndüren bir soyut yöntem veya özellik tanımlayın. Room sizin için e-postanın gövde kısmını oluşturur.
  • Uygulamanın tamamı için yalnızca bir Room veritabanı örneği gerekir. Bu nedenle, RoomDatabase öğesini tekil yapın.
  • Veritabanı yoksa veritabanını oluşturmak için Room'ın veritabanı oluşturucusunu kullanın. Aksi takdirde mevcut veritabanını döndürün.

1. adım: Veritabanını oluşturun

  1. database paketinde SleepDatabase.kt öğesini açın.
  2. Dosyada, RoomDatabase sınıfını genişleten abstract sınıfını SleepDatabase adıyla oluşturun.

    Sınıfı @Database ile açıklama olarak ekleyin.
@Database()
abstract class SleepDatabase : RoomDatabase() {}
  1. Eksik öğeler ve sürüm parametreleriyle ilgili bir hata görürsünüz. @Database ek açıklamasının, Room veritabanını oluşturabilmesi için birkaç bağımsız değişken gerekir.
  • SleepNight öğesini, entities listesiyle birlikte tek öğe olarak sağlayın.
  • version değerini 1olarak ayarlayın. Şemayı her değiştirdiğinizde sürüm numarasını artırmanız gerekir.
  • Şema sürümü geçmişi yedeklerini tutmamak için exportSchema değerini false olarak ayarlayın.
entities = [SleepNight::class], version = 1, exportSchema = false
  1. Veritabanının DAO hakkında bilgi sahibi olması gerekir. Sınıfın gövdesinde, SleepDatabaseDao değerini döndüren bir soyut değer tanımlayın. Birden fazla DAO'nuz olabilir.
abstract val sleepDatabaseDao: SleepDatabaseDao
  1. Bunun altında bir companion nesnesi tanımlayın. Yardımcı nesne, istemcilerin sınıfı örneklemeden veritabanı oluşturma veya alma yöntemlerine erişmesine olanak tanır. Bu sınıfın tek amacı veritabanı sağlamak olduğundan, hiçbir zaman örnek oluşturulmasına gerek yoktur.
 companion object {}
  1. companion nesnesinin içinde, veritabanı için özel bir null değer atanabilir değişken INSTANCE tanımlayın ve bunu null olarak başlatın. Bir veritabanı oluşturulduktan sonra INSTANCE değişkeni, veritabanına referans vermeye devam eder. Bu, veri tabanıyla bağlantıları tekrar tekrar açmaktan kaçınmanıza yardımcı olur. Bu işlem maliyetlidir.

INSTANCE öğesine @Volatile ile not ekleyin. Geçici bir değişkenin değeri hiçbir zaman önbelleğe alınmaz ve tüm yazma ve okuma işlemleri ana belleğe ve ana bellekten yapılır. Bu, INSTANCE değerinin her zaman güncel ve tüm yürütme iş parçacıkları için aynı olmasını sağlar. Bu, bir iş parçacığı tarafından INSTANCE üzerinde yapılan değişikliklerin diğer tüm iş parçacıkları tarafından anında görülebildiği ve örneğin iki iş parçacığının her birinin önbellekteki aynı öğeyi güncellemesi gibi bir durumun yaşanmadığı anlamına gelir. Bu durum sorun yaratır.

@Volatile
private var INSTANCE: SleepDatabase? = null
  1. INSTANCE altında, companion nesnesinin içinde, veritabanı oluşturucunun ihtiyaç duyacağı bir Context parametresine sahip bir getInstance()yöntem tanımlayın. SleepDatabase türünü döndürür. getInstance() henüz herhangi bir değer döndürmediği için hata görürsünüz.
fun getInstance(context: Context): SleepDatabase {}
  1. getInstance() içine bir synchronized{} bloğu ekleyin. Bağlama erişebilmek için this iletin.

    Birden fazla iş parçacığı aynı anda bir veritabanı örneği isteyebilir ve bu da tek bir veritabanı yerine iki veritabanı oluşturulmasına neden olabilir. Bu sorunun bu örnek uygulamada yaşanma olasılığı düşüktür ancak daha karmaşık bir uygulamada yaşanabilir. Veritabanını synchronized içine almak için kodu sarmalama, bu kod bloğuna aynı anda yalnızca bir yürütme iş parçacığının girebileceği anlamına gelir. Bu da veritabanının yalnızca bir kez başlatılmasını sağlar.
synchronized(this) {}
  1. Senkronize edilmiş blokta, INSTANCE öğesinin geçerli değerini instance adlı yerel bir değişkene kopyalayın. Bu, yalnızca yerel değişkenlerde kullanılabilen akıllı yayın özelliğinden yararlanmak için yapılır.
var instance = INSTANCE
  1. synchronized bloğunun içinde, synchronized bloğunun sonunda return instance. Döndürülen tür uyuşmazlığı hatasını yoksayın. İşiniz bittiğinde hiçbir zaman null döndürmeyeceksiniz.
return instance
  1. return ifadesinin üstüne, instance değerinin boş olup olmadığını (yani henüz bir veritabanı olup olmadığını) kontrol etmek için bir if ifadesi ekleyin.
if (instance == null) {}
  1. instance null ise veritabanı almak için veritabanı oluşturucuyu kullanın. if ifadesinin gövdesinde Room.databaseBuilder öğesini çağırın ve ilettiğiniz bağlamı, veritabanı sınıfını ve veritabanı adını (sleep_history_database) sağlayın. Hatayı kaldırmak için bir taşıma stratejisi eklemeniz ve aşağıdaki adımlarda build() işlemini yapmanız gerekir.
instance = Room.databaseBuilder(
                           context.applicationContext,
                           SleepDatabase::class.java,
                           "sleep_history_database")
  1. Gerekli taşıma stratejisini oluşturucuya ekleyin. .fallbackToDestructiveMigration() kullanın.

    Normalde, şema değiştiğinde bir taşıma stratejisi içeren bir taşıma nesnesi sağlamanız gerekir. Taşıma nesnesi, eski şemaya sahip tüm satırları nasıl alıp yeni şemadaki satırlara dönüştüreceğinizi tanımlayan bir nesnedir. Böylece hiçbir veri kaybolmaz. Taşıma bu codelab'in kapsamı dışındadır. Basit bir çözüm, veritabanını yok edip yeniden oluşturmaktır. Bu durumda veriler kaybolur.
.fallbackToDestructiveMigration()
  1. Son olarak .build() numaralı telefonu arayın.
.build()
  1. if ifadesinde son adım olarak INSTANCE = instance değerini atayın.
INSTANCE = instance
  1. Son kodunuz aşağıdaki gibi görünmelidir:
@Database(entities = [SleepNight::class], version = 1, exportSchema = false)
abstract class SleepDatabase : RoomDatabase() {

   abstract val sleepDatabaseDao: SleepDatabaseDao

   companion object {

       @Volatile
       private var INSTANCE: SleepDatabase? = null

       fun getInstance(context: Context): SleepDatabase {
           synchronized(this) {
               var instance = INSTANCE

               if (instance == null) {
                   instance = Room.databaseBuilder(
                           context.applicationContext,
                           SleepDatabase::class.java,
                           "sleep_history_database"
                   )
                           .fallbackToDestructiveMigration()
                           .build()
                   INSTANCE = instance
               }
               return instance
           }
       }
   }
}
  1. Kodunuzu oluşturup çalıştırın.

Artık Room veritabanınızla çalışmak için gereken tüm yapı taşlarına sahipsiniz. Bu kod derlenip çalıştırılır ancak gerçekten çalışıp çalışmadığını anlamanın bir yolu yoktur. Bu nedenle, bazı temel testler eklemek için iyi bir zamandır.

2. adım: SleepDatabase'i test edin

Bu adımda, veritabanınızın çalıştığını doğrulamak için sağlanan testleri çalıştırırsınız. Bu, üzerine inşa etmeden önce veritabanının çalıştığından emin olmanıza yardımcı olur. Sağlanan testler basittir. Üretim uygulaması için tüm DAO'lardaki tüm işlevleri ve sorguları kullanırsınız.

Başlangıç uygulaması androidTest klasörü içerir. Bu androidTest klasörü, Android enstrümantasyonunu içeren birim testlerini içerir. Bu, testlerin Android çerçevesine ihtiyaç duyduğu anlamına gelir. Bu nedenle, testleri fiziksel veya sanal bir cihazda çalıştırmanız gerekir. Elbette, Android çerçevesini içermeyen saf birim testleri de oluşturup çalıştırabilirsiniz.

  1. Android Studio'da androidTest klasöründe SleepDatabaseTest dosyasını açın.
  2. Kodun yorumunu kaldırmak için yorumlanmış tüm kodu seçip Cmd+/ veya Control+/ klavye kısayoluna basın.
  3. Dosyaya göz atın.

Yeniden kullanabileceğiniz bir kod parçası olduğu için test koduna hızlıca göz atalım:

  • SleepDabaseTest, bir test sınıfıdır.
  • @RunWith ek açıklaması, testleri ayarlayan ve yürüten program olan test çalıştırıcıyı tanımlar.
  • Kurulum sırasında, @Before ile açıklama eklenen işlev yürütülür ve SleepDatabaseDao ile bellekte SleepDatabase oluşturur. "Bellek içi", bu veritabanının dosya sistemine kaydedilmediği ve testler çalıştırıldıktan sonra silineceği anlamına gelir.
  • Ayrıca, bellek içi veritabanı oluşturulurken kod, teste özel başka bir yöntemi (allowMainThreadQueries) çağırır. Varsayılan olarak, ana iş parçacığında sorgu çalıştırmaya çalıştığınızda hata alırsınız. Bu yöntem, yalnızca test sırasında yapmanız gereken ana iş parçacığında testler çalıştırmanıza olanak tanır.
  • @Test ile açıklama eklenmiş bir test yönteminde SleepNight oluşturur, ekler ve alır, ardından bunların aynı olduğunu onaylarsınız. Bir hata oluşursa istisna oluşturun. Gerçek bir testte birden fazla @Test yönteminiz olur.
  • Test tamamlandığında, veritabanını kapatmak için @After ile açıklama eklenmiş işlev yürütülür.
  1. Proje bölmesinde test dosyasını sağ tıklayın ve "SleepDatabaseTest"i çalıştır'ı seçin.
  2. Testler çalıştırıldıktan sonra SleepDatabaseTest bölmesinde tüm testlerin başarılı olduğunu doğrulayın.

Tüm testler başarılı olduğundan artık şunları biliyorsunuz:

  • Veritabanı doğru şekilde oluşturulur.
  • Veritabanına SleepNight ekleyebilirsiniz.
  • SleepNight geri alabilirsiniz.
  • SleepNight, kalite için doğru değere sahip.

Android Studio projesi: TrackMySleepQualityRoomAndTesting

Bir veritabanını test ederken DAO'da tanımlanan tüm yöntemleri uygulamanız gerekir. Testi tamamlamak için diğer DAO yöntemlerini kullanacak testler ekleyin ve bunları çalıştırın.

  • Tablolarınızı @Entity ile açıklama eklenmiş veri sınıfları olarak tanımlayın. @ColumnInfo ile açıklama eklenmiş özellikleri tablolarda sütun olarak tanımlayın.
  • Veri erişimi nesnesini (DAO) @Dao ile açıklama eklenmiş bir arayüz olarak tanımlayın. DAO, Kotlin işlevlerini veritabanı sorgularıyla eşler.
  • @Insert, @Delete ve @Update işlevlerini tanımlamak için ek açıklamaları kullanın.
  • Diğer tüm sorgular için parametre olarak bir SQLite sorgu dizesiyle @Query ek açıklamasını kullanın.
  • Veritabanı döndüren bir getInstance() işlevine sahip bir soyut sınıf oluşturun.
  • Veritabanınızın ve DAO'nunuzun beklendiği gibi çalıştığını test etmek için enstrümanlı testleri kullanın. Sağlanan testleri şablon olarak kullanabilirsiniz.

Udacity kursu:

Android Geliştirici Dokümanları:

Diğer belgeler ve makaleler:

Bu bölümde, bir eğitmenin yönettiği kurs kapsamında bu codelab'i tamamlayan öğrenciler için olası ödevler listelenmektedir. Eğitmen, aşağıdakileri yapmalıdır:

  • Gerekirse ödev atayın.
  • Öğrencilere ev ödevi ödevlerini nasıl göndereceklerini bildirin.
  • Ödevlere not verin.

Eğitmenler bu önerileri istedikleri kadar kullanabilir ve uygun olduğunu düşündükleri diğer ödevleri verebilirler.

Bu codelab'i kendi başınıza tamamlıyorsanız bilginizi test etmek için bu ödevleri kullanabilirsiniz.

Bu soruları yanıtlayın

1. Soru

Bir sınıfın Room veritabanında depolanacak bir öğeyi temsil ettiğini nasıl belirtirsiniz?

  • Sınıfı uzatın DatabaseEntity.
  • Sınıfa @Entity ile not ekleyin.
  • Sınıfa @Database ile not ekleyin.
  • Sınıfı RoomEntity ile genişletin ve @Room ile açıklama ekleyin.

2. Soru

DAO (veri erişim nesnesi), Room'nın Kotlin işlevlerini veritabanı sorgularıyla eşlemek için kullandığı bir arayüzdür.

Bir arayüzün Room veritabanı için bir DAO'yu temsil ettiğini nasıl belirtirsiniz?

  • Arayüzü genişletin RoomDAO.
  • Arayüzü EntityDao olarak genişletin, ardından DaoConnection() yöntemini uygulayın.
  • Arayüze @Dao ile not ekleyin.
  • Arayüze @RoomConnection ile not ekleyin.

3. Soru

Aşağıdaki ifadelerden hangileri Room veritabanı hakkında doğrudur? Uygun olan tüm seçenekleri işaretleyin.

  • Room veritabanı için tabloları açıklama eklenmiş veri sınıfları olarak tanımlayabilirsiniz.
  • Bir sorgudan LiveData döndürürseniz Room, LiveData değişirse LiveData değerini sizin için güncel tutar.
  • Her Room veritabanında yalnızca bir DAO olmalıdır.
  • Bir sınıfı Room veritabanı olarak tanımlamak için bu sınıfı RoomDatabase sınıfının alt sınıfı yapın ve @Database ile açıklama ekleyin.

4. Soru

Aşağıdaki açıklamalardan hangilerini @Dao arayüzünüzde kullanabilirsiniz? Uygun olan tüm seçenekleri işaretleyin.

  • @Get
  • @Update
  • @Insert
  • @Query

5. Soru

Veritabanınızın çalıştığını nasıl doğrulayabilirsiniz? Uygun olan tüm seçenekleri işaretleyin.

  • Araçlı testler yazın.
  • Veriler gösterilene kadar uygulamayı yazmaya ve çalıştırmaya devam edin.
  • DAO arayüzündeki yöntemlere yapılan çağrıları Entity sınıfındaki eşdeğer yöntemlere yapılan çağrılarla değiştirin.
  • verifyDatabase() kitaplığı tarafından sağlanan Room işlevini çalıştırın.

Bir sonraki derse geçin: 6.2 Coroutines ve Room

Bu kurstaki diğer codelab'lerin bağlantılarını Android Kotlin Hakkında Temel Bilgiler codelab'leri açılış sayfasında bulabilirsiniz.