Dieses Codelab ist Teil des Android Kotlin Fundamentals-Kurss. Sie profitieren von diesem Kurs, wenn Sie nacheinander die Codelabs durcharbeiten. Alle Kurs-Codelabs finden Sie auf der Landingpage für Kotlin-Grundlagen für Android-Entwickler.
Einführung
Die meisten Apps haben Daten, die gespeichert werden müssen, auch wenn der Nutzer die App schließt. Beispielsweise kann die App eine Playlist, ein Inventar von Spielelementen, Ausgaben und Einkommen, einen Katalog von Konstellationen oder Schlafdaten im Zeitverlauf speichern. In der Regel verwenden Sie eine Datenbank, um persistente Daten zu speichern.
Room
ist eine Datenbankbibliothek, die Teil von Android Jetpack ist. Room
übernimmt viele der Aufgaben beim Einrichten und Konfigurieren einer Datenbank und ermöglicht Ihrer App, über normale Funktionsaufrufe mit der Datenbank zu interagieren. hinter den Kulissen Room
ist eine Abstraktionsebene über einer SQLite-Datenbank. Verwenden Sie die Terminologie von Room
und die Abfragesyntax für komplexere Abfragen, da Sie das SQLite-Modell verwenden.
Die folgende Abbildung zeigt, wie die Room
-Datenbank in die allgemeine Architektur passt, die in diesem Kurs empfohlen wird.
Was Sie bereits wissen sollten
Sie sollten mit Folgendem vertraut sein:
- Eine einfache Benutzeroberfläche für eine Android-App erstellen
- Aktivitäten, Fragmente und Datenansichten verwenden
- Die Navigation zwischen Fragmenten und die Verwendung von Safe Args (ein Gradle-Plug-in) zur Übertragung von Daten zwischen Fragmenten.
- Modelle, Fabriken mit Modellen sowie
LiveData
und die zugehörigen Betrachter ansehen Diese Themen zu Architekturkomponenten werden in einem früheren Codelab in diesem Kurs behandelt. - Grundlegendes Verständnis von SQL-Datenbanken und der SQLite-Sprache In SQLite finden Sie eine kurze Übersicht oder Auffrischung.
Lerninhalte
Room
-Datenbank zum Erstellen von Daten erstellen und mit ihr interagieren- So erstellen Sie eine Datenklasse, mit der eine Tabelle in der Datenbank definiert wird.
- Anleitung zum Verwenden eines Datenzugriffsobjekts (Data Access Object, DAO), um Kotlin-Funktionen SQL-Abfragen zuzuordnen.
- So testen Sie, ob Ihre Datenbank funktioniert
Aufgaben
- Erstelle eine
Room
-Datenbank mit einer Schnittstelle für nächtliche Schlafdaten. - Testen Sie die Datenbank mit den bereitgestellten Tests.
In diesem Codelab erstellst du den Datenbankteil einer App, die die Schlafqualität verfolgt. Die App verwendet eine Datenbank, um Schlafdaten zu speichern.
Die App hat zwei Bildschirme, die durch Fragmente dargestellt werden, wie in der folgenden Abbildung dargestellt.
Auf dem ersten Bildschirm auf der linken Seite finden Sie Schaltflächen zum Starten und Beenden der Aufzeichnung. Auf dem Bildschirm werden alle Schlafdaten des Nutzers angezeigt. Mit der Schaltfläche Löschen werden alle Daten gelöscht, die die App für den Nutzer erfasst hat.
Auf dem zweiten Bildschirm rechts wird die Qualität des Schlafs angezeigt. In der App wird die Bewertung in numerischer Form dargestellt. Zu Entwicklungszwecken zeigt die App sowohl die Gesichtssymbole als auch ihre numerischen Entsprechungen an.
Der Ablauf für Nutzer sieht so aus:
- Der Nutzer öffnet die App und sieht den Schlaftracking-Bildschirm.
- Der Nutzer tippt auf die Schaltfläche Starten. Damit wird die Startzeit aufgezeichnet und angezeigt. Die Schaltfläche Starten ist deaktiviert und die Schaltfläche Beenden ist aktiviert.
- Der Nutzer tippt auf die Schaltfläche Beenden. Damit wird die Endzeit erfasst und der Bildschirm für die Schlafqualität geöffnet.
- Der Nutzer wählt ein Symbol für die Schlafqualität aus. Der Bildschirm wird geschlossen und der Tracking-Bildschirm zeigt die Schlafzeit und die Schlafqualität an. Die Schaltfläche Stopp ist deaktiviert und die Schaltfläche Starten ist aktiviert. Die App ist bereit für eine weitere Nacht.
- Die Schaltfläche Löschen ist immer dann verfügbar, wenn Daten in der Datenbank vorhanden sind. Wenn der Nutzer auf Löschen tippt, werden alle seine Daten gelöscht. Es wird keine Meldung angezeigt.
Für diese App wird eine vereinfachte Architektur verwendet, die im Folgenden im Kontext der vollständigen Architektur gezeigt wird. Die Anwendung verwendet nur die folgenden Komponenten:
- UI-Controller
- Modell und
LiveData
ansehen - Eine Raumdatenbank
Schritt 1: Start-App herunterladen und ausführen
- Laden Sie die App TrackMySleepquality-Starter von GitHub herunter.
- Erstelle die App und führe sie aus. Die App zeigt die UI für das
SleepTrackerFragment
-Fragment an, jedoch keine Daten. Die Tasten reagieren nicht auf Tippen.
Schritt 2: Start-App prüfen
- Sieh dir hier die Gradle-Dateien an:
- Gradle-Datei auf Projektebene
In derbuild.gradle
-Datei auf Projektebene sehen Sie die Variablen, die Bibliotheksversionen angeben. Die in der Starter-App verwendeten Versionen funktionieren gut zusammen mit dieser App. Nach Abschluss dieses Codelabs werden Sie möglicherweise von Android Studio aufgefordert, einige der Versionen zu aktualisieren. Sie können selbst entscheiden, ob Sie die in der App enthaltenen Versionen aktualisieren oder beibehalten möchten. Sollte eine Kompilierungsfehler auftreten, versuchen Sie es mit einer Kombination aus Bibliotheksversionen, die in der finalen Lösung-App verwendet werden. - Die Gradle-Datei des Moduls. Sie sehen die bereitgestellten Abhängigkeiten für alle Android Jetpack-Bibliotheken, einschließlich
Room
, und die Abhängigkeiten für Koroutinen.
- Sehen Sie sich die Pakete und die Benutzeroberfläche an. Die App ist nach Funktionen strukturiert. Das Paket enthält Platzhalterdateien, die Sie durch das Hinzufügen von Code zu dieser Codelab-Reihe ergänzen.
- Das
database
-Paket für den gesamten Code, der sich auf die DatenbankRoom
bezieht. - Die Pakete
sleepquality
undsleeptracker
enthalten für jeden Bildschirm das Fragment, die Modellansicht und die Modellfabrik.
- In der
Util.kt
-Datei finden Sie Funktionen, mit denen Sie die Qualität Ihres Schlafs ermitteln können. Etwas Code ist auskommentiert, weil er auf ein Ansichtsmodell verweist, das Sie später erstellen. - Sehen Sie sich den AndroidTest-Ordner (
SleepDatabaseTest.kt
) an. Mit diesem Test können Sie prüfen, ob die Datenbank wie vorgesehen funktioniert.
Unter Android werden die Daten in Datenklassen dargestellt. Der Zugriff auf diese Daten erfolgt durch Funktionsaufrufe. In der Datenbankwelt sind jedoch Entitäten und Abfragen erforderlich.
- Eine Entität ist ein Objekt oder Konzept mit seinen Eigenschaften, das in der Datenbank gespeichert werden soll. Eine Entitätsklasse definiert eine Tabelle und jede Instanz dieser Klasse stellt eine Zeile in der Tabelle dar. Jedes Attribut definiert eine Spalte. Die Entität enthält Informationen zu einem nächtlichen Schlaf.
- Eine Abfrage ist eine Anfrage für Daten oder Informationen aus einer Datenbanktabelle oder -kombination oder eine Anfrage für eine Aktion für die Daten. Allgemeine Abfragen beziehen sich auf das Abrufen, Einfügen und Aktualisieren von Entitäten. Sie können beispielsweise alle aufgezeichneten Schlafnächte abfragen, sortiert nach Startzeit.
Mit „Room
“ erledigen Sie den Großteil der Arbeit von Kotlin-Datenklassen zu Entitäten, die in SQLite-Tabellen gespeichert werden können, von Funktionsdeklarationen bis SQL-Abfragen.
Sie müssen jede Entität als annotierte Datenklasse und die Interaktionen als annotierte Schnittstelle, ein Datenzugriffsobjekt (DAO), definieren. Room
nutzt diese annotierten Klassen, um Tabellen in der Datenbank zu erstellen sowie Abfragen zu erstellen, die auf die Datenbank reagieren.
Schritt 1: SleepNight-Entität erstellen
In dieser Aufgabe legen Sie eine Nacht des Schlafs als annotierte Datenklasse fest.
Für eine Nacht solltest du die Startzeit, das Ende und eine Qualitätsbewertung erfassen.
Außerdem brauchst du eine ID, um die Nacht eindeutig zu identifizieren.
- Suchen Sie im Paket
database
die DateiSleepNight.kt
und öffnen Sie sie. - Erstelle die
SleepNight
-Datenklasse mit Parametern für eine ID, eine Startzeit (in Millisekunden), eine Endzeit (in Millisekunden) und eine numerische Bewertung der Schlafqualität.
- Sie müssen
sleepQuality
initialisieren. Legen Sie dafür den Wert-1
fest, damit keine Qualitätsdaten erfasst wurden. - Außerdem müssen Sie das Ende initialisieren. Stelle es auf die Startzeit, um anzuzeigen, dass noch keine Endzeit aufgezeichnet wurde.
data class SleepNight(
var nightId: Long = 0L,
val startTimeMilli: Long = System.currentTimeMillis(),
var endTimeMilli: Long = startTimeMilli,
var sleepQuality: Int = -1
)
- Vor der Klassendeklaration geben Sie die Datenklasse mit
@Entity
an. Tabelle benennen:daily_sleep_quality_table
Das Argument fürtableName
ist optional, wird aber empfohlen. Du kannst in der Dokumentation nach anderen Argumenten suchen.
Wenn du dazu aufgefordert wirst, importiereEntity
und alle anderen Annotationen aus der Bibliothekandroidx
.
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(...)
- Wenn
nightId
als Primärschlüssel verwendet werden soll, vermerke das AttributnightId
mit@PrimaryKey
. Setzen Sie den ParameterautoGenerate
auftrue
, sodassRoom
die ID für jede Entität generiert. Das garantiert, dass die ID für jede Übernachtung eindeutig ist.
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,...
- Versieh die übrigen Properties mit
@ColumnInfo
. Passen Sie die Property-Namen mithilfe von Parametern wie unten beschrieben an.
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
)
- Erstellen Sie Ihren Code und führen Sie ihn aus, um sicherzustellen, dass er keine Fehler enthält.
In dieser Aufgabe definieren Sie ein Datenzugriffsobjekt. Auf Android-Geräten bietet der DAO praktische Methoden zum Einfügen, Löschen und Aktualisieren der Datenbank.
Wenn Sie eine Room
-Datenbank verwenden, abfragen Sie die Datenbank ab, indem Sie Kotlin-Funktionen im Code definieren und aufrufen. Diese Kotlin-Funktionen werden SQL-Abfragen zugeordnet. Sie definieren diese Zuordnungen in einem DAO mithilfe von Annotationen. Room
erstellt den erforderlichen Code.
Stellen Sie sich einen DAO als eine benutzerdefinierte Schnittstelle für den Zugriff auf Ihre Datenbank vor.
Bei häufigen Datenbankvorgängen enthält die Bibliothek Room
Annotationen wie @Insert
, @Delete
und @Update
. Andernfalls gibt es die Annotation @Query
. Sie können jede Abfrage schreiben, die von SQLite unterstützt wird.
Wenn Sie Ihre Abfragen in Android Studio erstellen, prüft der Compiler Ihre SQL-Abfragen auf Syntaxfehler.
Für die Schlaf-Tracker-Datenbank des Schlafs müssen Sie Folgendes tun können:
- Fügen Sie neue Übernachtungen ein.
- Aktualisieren Sie eine bestehende Nacht, um ein Ende und eine Qualitätsbewertung zu ändern.
- Rufen Sie eine bestimmte Nacht anhand ihres Schlüssels ab.
- Alle Nächte erhalten, damit Sie sie sehen können
- Hol dir die letzte Nacht.
- Löschen Sie alle Einträge in der Datenbank.
Schritt 1: SleepDatabase-DAO erstellen
- Öffnen Sie im Paket
database
das FeldSleepDatabaseDao.kt
. - Beachten Sie, dass
interface
SleepDatabaseDao
mit@Dao
annotiert ist. Alle DAOs müssen mit dem Keyword@Dao
versehen werden.
@Dao
interface SleepDatabaseDao {}
- Füge im Text der Schnittstelle eine
@Insert
-Annotation hinzu. Fügen Sie unter@Insert
eineinsert()
-Funktion hinzu, die eine Instanz derEntity
-KlasseSleepNight
als Argument verwendet.
Richtig.Room
generiert den erforderlichen Code, umSleepNight
in die Datenbank einzufügen. Wenn Sieinsert()
aus Ihrem Kotlin-Code aufrufen, führtRoom
eine SQL-Abfrage aus, um die Entität in die Datenbank einzufügen. (Hinweis: Sie können die Funktion beliebig aufrufen.)
@Insert
fun insert(night: SleepNight)
- Füge eine
@Update
-Annotation mit einerupdate()
-Funktion für eineSleepNight
hinzu. Die Entität, die aktualisiert wurde, ist die Entität, die denselben Schlüssel wie die übergebene Entität hat. Du kannst einige oder alle anderen Eigenschaften der Entität aktualisieren.
@Update
fun update(night: SleepNight)
Es gibt keine Komfort-Anmerkung für die verbleibende Funktionalität, daher müssen Sie die Annotation @Query
verwenden und SQLite-Abfragen bereitstellen.
- Füge eine
@Query
-Anmerkung mit einerget()
-Funktion hinzu, die das ArgumentLong
key
übernimmt und eine NULL-gültigeSleepNight
zurückgibt. Ihnen wird eine Fehlermeldung aufgrund eines fehlenden Parameters angezeigt.
@Query
fun get(key: Long): SleepNight?
- Die Abfrage wird als Stringparameter in der Anmerkung bereitgestellt. Fügen Sie
@Query
einen Parameter hinzu. Machen Sie es zu einerString
-Abfrage.
- Alle Spalten der
daily_sleep_quality_table
auswählen WHERE
entsprichtnightId
dem Argument "key
".
Das ist der:key
. Sie verwenden die Doppelpunktschreibung in der Abfrage, um auf Argumente in der Funktion zu verweisen.
("SELECT * from daily_sleep_quality_table WHERE nightId = :key")
- Fügen Sie
@Query
noch einmal mit einerclear()
-Funktion und einer SQLite-Abfrage zuDELETE
vondaily_sleep_quality_table
hinzu. Durch diese Abfrage wird die Tabelle selbst nicht gelöscht.
Mit der Annotation@Delete
wird ein Element gelöscht. Du kannst beispielsweise@Delete
verwenden und eine Liste der Übernachtungen angeben, die gelöscht werden sollen. Der Nachteil besteht darin, dass Sie die Tabelleninformationen abrufen oder kennen müssen. Die Annotation@Delete
eignet sich hervorragend zum Löschen bestimmter Einträge. Für das Löschen aller Einträge aus einer Tabelle ist sie jedoch nicht effizient.
@Query("DELETE FROM daily_sleep_quality_table")
fun clear()
- Fügen Sie einen
@Query
mit einergetTonight()
-Funktion hinzu. Setzen Sie die vongetTonight()
zurückgegebeneSleepNight
auf NULL, damit die Funktion die Groß- und Kleinschreibung verarbeiten kann, wenn die Tabelle leer ist. Die Tabelle ist anfangs leer und nach dem Löschen der Daten.
Wenn Sie aus der Datenbank eine Abfrage abrufen möchten, schreiben Sie eine SQLite-Abfrage, mit der das erste Element einer Liste von Ergebnissen nachnightId
in absteigender Reihenfolge zurückgegeben wird. VerwendeLIMIT 1
, um nur ein Element zurückzugeben.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC LIMIT 1")
fun getTonight(): SleepNight?
- Füge ein
@Query
mit einergetAllNights()
-Funktion hinzu:
- Lassen Sie die SQLite-Abfrage alle Spalten aus der
daily_sleep_quality_table
zurückgeben, sortiert in absteigender Reihenfolge. getAllNights()
muss eine Liste vonSleepNight
-Entitäten alsLiveData
zurückgeben.Room
hält diesenLiveData
für Sie auf dem neuesten Stand. Sie müssen also die Daten nur einmal abrufen.- Möglicherweise müssen Sie
LiveData
ausandroidx.lifecycle.LiveData
importieren.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC")
fun getAllNights(): LiveData<List<SleepNight>>
- Die sichtbaren Änderungen werden zwar nicht angezeigt, Führe deine App aber noch einmal aus, um sicherzustellen, dass sie keine Fehler enthält.
In dieser Aufgabe erstellen Sie eine Room
-Datenbank, die die Entity
und den DAO verwendet, die Sie in der vorherigen Aufgabe erstellt haben.
Sie müssen eine abstrakte Inhaber-Klasse für die Datenbank erstellen, die mit @Database
gekennzeichnet ist. Diese Klasse hat eine Methode, die entweder eine Instanz der Datenbank erstellt, wenn die Datenbank nicht existiert, oder einen Verweis auf eine vorhandene Datenbank zurückgibt.
Das Abrufen einer Room
-Datenbank ist etwas kompliziert. Hier ist der allgemeine Ablauf hier, bevor Sie mit dem Code beginnen:
- Erstelle eine
public abstract
-Klasse, dieextends RoomDatabase
. Diese Klasse dient als Datenbankinhaber. Die Klasse ist abstrakt, daRoom
die Implementierung für Sie erstellt. - Annotieren Sie den Kurs mit
@Database
. Geben Sie in den Argumenten die Entitäten für die Datenbank an und legen Sie die Versionsnummer fest. - Definiere in einem
companion
-Objekt eine abstrakte Methode oder Eigenschaft, die einSleepDatabaseDao
zurückgibt. Der Text wird vonRoom
generiert. - Da Sie nur eine Instanz der
Room
-Datenbank für die gesamte Anwendung benötigen, machen Sie dieRoomDatabase
zu einem Singleton. - Mit dem Datenbank-Builder von
Room
können Sie die Datenbank nur erstellen, wenn sie nicht vorhanden ist. Andernfalls wird die vorhandene Datenbank zurückgegeben.
Schritt 1: Datenbank erstellen
- Öffnen Sie im Paket
database
das FeldSleepDatabase.kt
. - Erstellen Sie in der Datei eine
abstract
-Klasse namensSleepDatabase
, dieRoomDatabase
erweitert.
Annotieren Sie den Kurs mit@Database
.
@Database()
abstract class SleepDatabase : RoomDatabase() {}
- Ihnen wird eine Fehlermeldung für fehlende Entitäten und Versionsparameter angezeigt. Die Annotation
@Database
erfordert mehrere Argumente, damitRoom
die Datenbank erstellen kann.
- Geben Sie
SleepNight
als einzigen Artikel mit der Listeentities
an. - Legen Sie
version
als1
fest. Jedes Mal, wenn Sie das Schema ändern, müssen Sie die Versionsnummer erhöhen. - Setzen Sie
exportSchema
auffalse
, damit keine Sicherungen des Schemaversionsverlaufs gespeichert werden.
entities = [SleepNight::class], version = 1, exportSchema = false
- Die Datenbank muss den DAO kennen. Geben Sie im Textkörper der Klasse einen abstrakten Wert an, der
SleepDatabaseDao
zurückgibt. Sie können mehrere DAOs haben.
abstract val sleepDatabaseDao: SleepDatabaseDao
- Definieren Sie darunter ein
companion
-Objekt. Das Companion-Objekt ermöglicht Clients den Zugriff auf die Methoden zum Erstellen oder Abrufen der Datenbank, ohne die Klasse zu instanziieren. Da der einzige Zweck dieser Klasse darin besteht, eine Datenbank bereitzustellen, ist es nie sinnvoll, sie zu instanziieren.
companion object {}
- Erklären Sie im
companion
-Objekt eine private Null-VariableINSTANCE
für die Datenbank und initialisieren Sie sie innull
. Die VariableINSTANCE
behält einen Verweis auf die Datenbank bei, sobald eine erstellt wurde. So vermeiden Sie, dass Sie immer wieder Verbindungen zur Datenbank öffnen müssen, was teuer ist.
Annotieren Sie INSTANCE
mit @Volatile
. Der Wert einer flüchtigen Variablen wird nie im Cache gespeichert und alle Schreibvorgänge und Lesevorgänge erfolgen im und vom Hauptarbeitsspeicher. So ist der Wert von INSTANCE
immer auf dem neuesten Stand und für alle Ausführungsthreads gleich. Das bedeutet, dass Änderungen, die an einem Thread an INSTANCE
vorgenommen werden, sofort für alle anderen Threads sichtbar sind. Sie erhalten z. B. keine Situation, in der zwei Threads dieselbe Entität in einem Cache aktualisieren. Das würde zu einem Problem führen.
@Volatile
private var INSTANCE: SleepDatabase? = null
- Definieren Sie unter
INSTANCE
noch imcompanion
-Objekt einegetInstance()
-Methode mit einemContext
-Parameter, den der Datenbank-Builder benötigt. Geben Sie einen TypSleepDatabase
zurück. Sie sehen eine Fehlermeldung, dagetInstance()
noch nichts zurückgibt.
fun getInstance(context: Context): SleepDatabase {}
- Fügen Sie in
getInstance()
einensynchronized{}
-Block ein. Übergeben Siethis
, damit Sie auf den Kontext zugreifen können.
Mehrere Threads können gleichzeitig nach einer Datenbankinstanz fragen. Dies führt zu zwei statt einer Datenbank. In dieser Beispiel-App tritt dieses Problem wahrscheinlich nicht auf. Bei einer komplexeren App ist das aber möglich. Wenn Sie den Code umschließen, um die Datenbank insynchronized
zu speichern, kann der Codeblock nur jeweils für einen Ausführungsthread eingegeben werden. Dadurch wird die Datenbank nur einmal initialisiert.
synchronized(this) {}
- Kopieren Sie im synchronisierten Block den aktuellen Wert von
INSTANCE
in die lokale Variableinstance
. Hierdurch wird Smart Cast genutzt, das nur für lokale Variablen verfügbar ist.
var instance = INSTANCE
- Im
synchronized
-Block befindet sichreturn instance
am Ende dessynchronized
-Blocks. Ignorieren Sie den Fehler wegen nicht übereinstimmender Rückgabetypen. Nach der Fertigstellung werden keine Werte zurückgegeben.
return instance
- Fügen Sie oberhalb der Anweisung
return
eineif
-Anweisung hinzu, um zu prüfen, obinstance
null ist, wenn also noch keine Datenbank vorhanden ist.
if (instance == null) {}
- Wenn
instance
den Wertnull
hat, verwenden Sie den Database Builder, um eine Datenbank abzurufen. Rufen Sie im Text derif
-AnweisungRoom.databaseBuilder
auf und geben Sie den übergebenen Kontext, die Datenbankklasse und den Namen der Datenbanksleep_history_database
an. Um den Fehler zu entfernen, müssen Sie in den folgenden Schritten eine Migrationsstrategie undbuild()
hinzufügen.
instance = Room.databaseBuilder(
context.applicationContext,
SleepDatabase::class.java,
"sleep_history_database")
- Fügen Sie dem Builder die erforderliche Migrationsstrategie hinzu. Verwende
.fallbackToDestructiveMigration()
.
In der Regel musst du ein Migrationsobjekt mit einer Migrationsstrategie für den Zeitpunkt angeben, an dem sich das Schema ändert. Ein Migrationsobjekt ist ein Objekt, das definiert, wie alle Zeilen mit dem alten Schema aufgenommen werden, und sie in Zeilen im neuen Schema umwandeln, damit keine Daten verloren gehen. Migration wird in diesem Codelab nicht genutzt. Eine einfache Lösung ist das Löschen und Neubau der Datenbank, wodurch die Daten verloren gehen.
.fallbackToDestructiveMigration()
- Rufen Sie schließlich
.build()
auf.
.build()
- Weisen Sie
INSTANCE = instance
als letzten Schritt in derif
-Anweisung zu.
INSTANCE = instance
- Der endgültige Code sollte so aussehen:
@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
}
}
}
}
- Erstellen Sie Ihren Code und führen Sie ihn aus.
Sie haben jetzt alle Grundbausteine für Ihre Room
-Datenbank. Dieser Code wird kompiliert und ausgeführt, aber Sie können nicht feststellen, ob er tatsächlich funktioniert. Jetzt ist es an der Zeit, einige grundlegende Tests hinzuzufügen.
Schritt 2: SleepDatabase testen
In diesem Schritt testen Sie, ob die Datenbank funktioniert. Dadurch wird sichergestellt, dass die Datenbank funktioniert, bevor Sie darauf aufbauen. Die bereitgestellten Tests sind einfach. Bei einer Produktions-App würden Sie alle Funktionen und Abfragen in allen DAOs ausführen.
Die Starter-App enthält einen androidTest-Ordner. Dieser androidTest-Ordner enthält Einheitentests, die Android-Instrumentierung beinhalten. Das ist fälschlicherweise so, dass die Tests das Android-Framework erfordern. Sie müssen die Tests also auf einem physischen oder virtuellen Gerät durchführen. Selbstverständlich können Sie auch reine Unittests erstellen und durchführen, die das Android-Framework nicht beinhalten.
- Öffnen Sie in Android Studio im Ordner androidTest die Datei SleepDatabaseTest.
- Wenn du die Kommentierung des Codes aufheben möchtest, wähle den gesamten kommentierten Code aus und drücke die Tastenkombination
Cmd+/
oderControl+/
. - Sehen Sie sich die Datei an.
Hier ein kurzer Überblick über den Testcode, den du wiederverwenden kannst:
SleepDabaseTest
ist eine Testklasse.- Die Annotation
@RunWith
gibt den Test-Ausführer an, also das Programm, das die Tests einrichtet und ausführt. - Während der Einrichtung wird die mit
@Before
annotierte Funktion ausgeführt und erstellt eine speicherinterneSleepDatabase
mit derSleepDatabaseDao
. „In-Memory“ bedeutet, dass diese Datenbank nicht im Dateisystem gespeichert und nach Ablauf der Tests gelöscht wird. - Außerdem ruft der Code beim Erstellen der In-Memory-Datenbank eine andere testspezifische Methode auf:
allowMainThreadQueries
. Wenn Sie versuchen, Abfragen im Hauptthread auszuführen, wird standardmäßig eine Fehlermeldung angezeigt. Mit dieser Methode können Sie Tests im Hauptthread ausführen. Dies sollten Sie nur während der Tests tun. - In einer mit
@Test
annotierten Testmethode erstellen, einfügen und abrufen Sie eineSleepNight
und behaupten, dass sie identisch sind. Wenn etwas nicht funktioniert, lösen Sie eine Ausnahme aus. In einem echten Test gibt es mehrere@Test
Methoden. - Wenn der Test abgeschlossen ist, wird die mit
@After
gekennzeichnete Funktion ausgeführt, um die Datenbank zu schließen.
- Klicken Sie im Bereich Projekt mit der rechten Maustaste auf die Testdatei und wählen Sie Ausführen 'SleepDatabaseTest' aus.
- Prüfen Sie nach dem Ausführen der Tests im Bereich SleepDatabaseTest, ob alle Tests bestanden wurden.
Da alle Tests bestanden wurden, wissen Sie jetzt mehrere Dinge:
- Die Datenbank wird korrekt erstellt.
- Sie können ein
SleepNight
in die Datenbank einfügen. - Du kannst
SleepNight
wiederherstellen. SleepNight
hat den richtigen Wert für die Qualität.
Android Studio-Projekt: TrackMySleepqualityRoomAndTesting
Beim Testen einer Datenbank müssen Sie alle in der DAO definierten Methoden anwenden. Um die Tests abzuschließen, können Sie Tests durchführen und die anderen DAO-Methoden ausführen.
- Definieren Sie Ihre Tabellen als Datenklassen, die mit
@Entity
gekennzeichnet sind. Definieren Sie mit@ColumnInfo
verknüpfte Spalten als Spalten in den Tabellen. - Legen Sie ein Datenzugriffsobjekt (DAO) als Schnittstelle mit Annotationen mit
@Dao
fest. Der DAO ordnet Kotlin-Funktionen Datenbankabfragen zu. - Mit Annotationen können Sie die Funktionen
@Insert
,@Delete
und@Update
definieren. - Verwenden Sie die Annotation
@Query
mit einem SQLite-Abfragestring als Parameter für alle anderen Abfragen. - Erstelle eine abstrakte Klasse mit einer
getInstance()
-Funktion, die eine Datenbank zurückgibt. - Mit instrumentierten Tests können Sie testen, ob Ihre Datenbank und der DAO wie erwartet funktionieren. Sie können die bereitgestellten Tests als Vorlage verwenden.
Udacity-Kurs:
Android-Entwicklerdokumentation:
RoomDatabase
Database
(Anmerkungen)- Sie können Rohabfragen mit
Room
verwenden. Roomdatabase.Builder
- Tests
SQLiteDatabase
-KlasseDao
Room
-Persistenzbibliothek
Weitere Dokumentationen und Artikel:
In diesem Abschnitt werden mögliche Hausaufgaben für Schüler oder Studenten aufgeführt, die an diesem von einem Kursleiter geleiteten Codelab arbeiten. Die Lehrkraft kann Folgendes tun:
- Bei Bedarf können Sie die entsprechenden Aufgaben zuweisen.
- Schülern mitteilen, wie sie Aufgaben für die Aufgabe abgeben
- Benoten Sie die Hausaufgaben.
Lehrkräfte können diese Vorschläge so oft oder so oft verwenden, wie sie möchten. anderen Aufgaben können sie nach Belieben zugewiesen werden.
Wenn Sie alleine an diesem Codelab arbeiten, können Sie Ihr Wissen mit diesen Hausaufgaben testen.
Diese Fragen beantworten
Frage 1
Wie geben Sie an, dass eine Klasse eine Entität darstellt, die in einer Room
-Datenbank gespeichert werden soll?
- Machen Sie den Kurs um
DatabaseEntity
. - Annotieren Sie den Kurs mit
@Entity
. - Annotieren Sie den Kurs mit
@Database
. - Erweitern Sie den Kurs um
RoomEntity
und versehen Sie ihn mit@Room
.
Frage 2
Der DAO (data access object) ist eine Schnittstelle, die Room
verwendet, um Kotlin-Funktionen Datenbankabfragen zuzuordnen.
Wie geben Sie an, dass eine Schnittstelle einen DAO für eine Room
-Datenbank darstellt?
- Erweitern Sie die Schnittstelle um
RoomDAO
. - Dafür muss die Schnittstelle
EntityDao
erweitern und dann die MethodeDaoConnection()
implementieren. - Annotieren Sie die Schnittstelle mit
@Dao
. - Annotieren Sie die Schnittstelle mit
@RoomConnection
.
Frage 3
Welche der folgenden Aussagen über die Room
-Datenbank trifft zu? Wählen Sie alle zutreffenden Antworten aus.
- Sie können Tabellen für eine
Room
-Datenbank als annotierte Datenklassen definieren. - Wenn du
LiveData
von einer Abfrage aus zurückgibst, wirdRoom
für dichLiveData
aktualisiert, wenn sich derLiveData
ändert. - Jede
Room
-Datenbank muss genau eine DAO haben. - Wenn Sie eine Klasse als
Room
-Datenbank kennzeichnen möchten, machen Sie sie zu einer Unterklasse vonRoomDatabase
und annotieren Sie sie mit@Database
.
Frage 4
Welche der folgenden Annotationen können Sie in Ihrer @Dao
-Schnittstelle verwenden? Wählen Sie alle zutreffenden Antworten aus.
@Get
@Update
@Insert
@Query
Frage 5
Wie können Sie überprüfen, ob Ihre Datenbank funktioniert? Wählen Sie alle zutreffenden Antworten aus.
- Instrumentierte Tests schreiben.
- Schreiben Sie die App und führen Sie sie aus, bis die Daten angezeigt werden.
- Ersetzen Sie die Aufrufe der Methoden in der DAO-Schnittstelle durch Aufrufe gleichwertiger Methoden in der Klasse
Entity
. - Führe die Funktion
verifyDatabase()
aus, die von der BibliothekRoom
bereitgestellt wird.
Beginnen Sie mit der nächsten Lektion:
Links zu anderen Codelabs in diesem Kurs finden Sie auf der Landingpage zu Kotlin-Grundlagen für Android.