Database Views mit Room für Android

Room ist eine Abstraktionsschicht über SQLite, die Google als AndroidX-Bibliothek verpackt hat und auch empfiehlt. Seit Version 2.1 bietet Room die Möglichkeit, Database Views, auch bekannt als gespeicherte Abfragen, hinzuzufügen.

Einige der guten Gründe für die Verwendung von Database Views sind:

  • Sie erleichtern das Schreiben komplexer Abfragen und deren Verwendung in Data Access Object (DAO)-Abfragen.
  • Sie können nur die Felder abfragen, die Sie benötigen, und müssen nicht alle Felder in einer Tabelle durchgehen.

In diesem Lernprogramm werden Sie eine Kundenumfrage-App erstellen, mit der die Kunden eines Restaurants ihr Feedback abgeben können, und dieses Feedback dann in einer von Room verwalteten Datenbank speichern. Während des Prozesses lernen Sie Folgendes:

  • Was ist eine Datenbankansicht?
  • Wie erstellt man Datenbankansichten?
  • Wie verwendet man sie, um das Schreiben von SELECT-Abfragen zu vereinfachen
Hinweis: Dieses Tutorial setzt voraus, dass Sie Erfahrung mit der Entwicklung für Android in Kotlin haben und bereits mit Room gearbeitet haben. Wenn Sie mit Room nicht vertraut sind, schauen Sie sich unser Tutorial zur Datenpersistenz mit Room an.

Dieses Tutorial verwendet auch Coroutines mit Room. Um mehr zu erfahren, lesen Sie unser Tutorial Coroutines with Room Persistence Library.

Getting Started

Laden Sie das Starterprojekt herunter, indem Sie auf die Schaltfläche Download Materials am oberen oder unteren Rand dieses Tutorials klicken.

Extrahieren Sie die ZIP-Datei und öffnen Sie das Starterprojekt in Android Studio 4.0 oder höher, indem Sie auf dem Begrüßungsbildschirm die Option Open an existing Android Studio project wählen.

Nachdem die Gradle-Synchronisierung abgeschlossen ist, erkunden Sie die Projektstruktur. Das Projekt folgt der MVVM-Architektur, sodass ähnliche Funktionalitäten in einem Paket zusammengefasst sind. Machen Sie sich mit den vorhandenen Paketen vertraut – Sie werden sie in diesem Tutorial verwenden.

Build und starten. Sie werden einen einfachen Bildschirm mit einer Willkommensnachricht, einem Bild und einer Schaltfläche START SURVEY sehen.

Bildschirm

Tippen Sie auf die Schaltfläche „UMFRAGE STARTEN“. Für die Zwecke dieses Tutorials können Sie die Tatsache ignorieren, dass Sie nicht im Restaurant gegessen haben. :]

Der nächste Bildschirm ist der Umfrage-Bildschirm. Er enthält ein E-Mail-Eingabefeld, Optionsfelder zur Auswahl des zu bewertenden Gerichts und drei Fragen. Unter jeder Frage befinden sich die Schaltflächen „Gut“, „Durchschnitt“ und „Schlecht“, so dass der Benutzer seine Zufriedenheit bewerten kann.

Der Umfrage-Bildschirm der Kundenumfrage-App mit Fragen und möglichen Bewertungen

Sie sehen auch die Schaltfläche UMFRAGE SENDEN. Wenn Sie darauf tippen, erscheint ein Toast, der besagt, dass es noch nicht Zeit ist, die Umfrage durchzuführen. Keine Sorge, das wird im Laufe dieses Tutorials korrigiert.

Du bist jetzt im The View Restaurant willkommen, wo du eine atemberaubende Aussicht auf die Natur genießen, die köstlichen Gerichte probieren und deine Zufriedenheit bewerten kannst. Dabei werden Sie auch etwas über die Datenbankansichten von Room erfahren.

Verwendung von Datenbankansichten

Betrachten Sie eine Tabelle, die der Einfachheit halber zusätzliche Funktionen von vorgefertigten SELECT-Abfragen hat. Room Version 2.1 und höher bezeichnet diese als Database View und bietet eine Anmerkung mit dem gleichen Namen, z.B. @DatabaseView.

Mit dieser Annotation können Sie eine Klasse so kennzeichnen, dass sie sich wie eine Datenbankansicht verhält. Dies ermöglicht es Ihnen, eine Abfrage an die Klasse anzuhängen, wie unten:

@DatabaseView("SELECT user.id, user.name " + "AS departmentName FROM user " + "WHERE user.departmentId = department.id")class User { var id: Long = 0 var name: String? = null}

Sie können dann diese Klasse in Ihrem DAO verwenden, um Daten auf die gleiche Weise abzufragen, wie Sie es mit einer Klasse tun würden, die als Entität, d.h. als Tabelle in einer Datenbank, markiert ist.

Ein DAO hilft Ihnen, auf Daten aus der Datenbank Ihrer Anwendung zuzugreifen. Sie enthält typischerweise die CUD-Methoden (Create, Update und Delete) und kann auch andere Methoden enthalten, die für den Lese- und Schreibzugriff auf die Datenbank notwendig sind.

Die Beziehung zwischen Database Views und der Datenbank ist ähnlich wie die Beziehung zwischen Entities und der Datenbank. Wir werden uns diese Beziehungen im nächsten Schritt genauer ansehen.

Vergleich zwischen einer Datenbankansicht und einer Entität

Klassen, die mit @DatabaseView annotiert sind, ähneln den Entity-Klassen. Hier ist, wie:

  • Beide können SELECT FROM in DAO-Abfragen verwenden.
  • Database Views und Entitys können beide @ColumnInfo verwenden, was Ihnen erlaubt, die Spalteninformationen, die mit einem Feld verbunden sind, anzupassen.
  • Sie können beide @Embedded verwenden, was einem Feld erlaubt, verschachtelte Felder zu haben, auf die Abfragen direkt verweisen können.

Während es viele Ähnlichkeiten zwischen den beiden gibt, gibt es auch Unterschiede zwischen DatabaseViews und Entitys:

  • Sie können INSERT, UPDATE und DELETE mit einem Entity verwenden, aber nicht mit einem DatabaseView.
  • Sie definieren alle Ihre Ansichten in Ihren Anwendungen mit views, aber Sie definieren Entitäten mit entities.

Nun, da Sie wissen, was eine DatabaseView ist und wie sie sich von einer Entity-Klasse unterscheidet, ist es an der Zeit, sie zu verwenden und die Umfrage für The View Restaurant zu starten.

Senden der Umfrage

Der erste Schritt besteht darin, die Logik zum Senden der Umfrage und zum Speichern in der Room-Datenbank hinzuzufügen, nachdem Sie auf die Schaltfläche SURVEY SENDEN getippt haben.

Navigieren Sie zu customersurveys/CustomerSurveyFragment.kt, wo Sie die Logik zum Erfassen der Beantwortungen und zum Speichern in Room hinzufügen werden. Ersetzen Sie dazu den Code in submitSurvey() durch den folgenden:

// 1val email = editEmail.text.toString()// 2if (validateEmail(email)) { // 3 val meal = when (radioGroupMeals.checkedRadioButtonId) { R.id.radioBreakfast -> "Breakfast" R.id.radioLunch -> "Lunch" R.id.radioDinner -> "Dinner" else -> "No Meal" } // 4 val customerSurvey = SurveyListItem .CustomerSurvey(0, email, meal, questionOneAnswer, questionTwoAnswer, questionThreeAnswer) customerSurveyViewModel.insertCustomerSurvey(customerSurvey) // 5 findNavController() .navigate(R.id.action_surveyFragment_to_surveyCompletedFragment)}

Mit diesem Code gehen Sie folgendermaßen vor:

  1. Sie erhalten die E-Mail aus editEmail und weisen sie einer Variablen zu: email.
  2. Diese Bedingungsprüfung ruft validateEmail(email) auf, die prüft, ob die E-Mail null ist oder nicht. Sie gibt false zurück, wenn sie null ist. Außerdem wird geprüft, ob die eingegebene E-Mail gültig ist, und wenn nicht, wird false zurückgegeben.
  3. Der Code innerhalb der Anweisung if wird ausgeführt, wenn validateEmail(email) true zurückgibt. meal enthält die Art der Mahlzeit, die der Benutzer aus den Optionsgruppen ausgewählt hat.
  4. Wenn Sie den Wert von meal haben, erstellen Sie SurveyListItem.CustomerSurvey, der alle Informationen über die Umfrage enthält. Es zieht die Werte für questionOneAnswer, questionTwoAnswer und questionThreeAnswer aus toggleButtonListeners(), das zu diesem Zweck Hörer hat.
  5. Hier speichern Sie customerSurvey, indem Sie insertCustomerSurvey(customerSurvey) in CustomerSurveyViewModel aufrufen, das die Logik zum Speichern in Room übernimmt.
  6. Sie navigieren zu SurveyCompletedFragment.

Nach dem Hinzufügen dieses Elements werden Sie feststellen, dass customerSurveyViewModel und findNavController() rot unterstrichen sind. Um dies zu beheben, fügen Sie zunächst die CustomerSurveyViewModel-Initialisierung am Anfang der Klasse hinzu, direkt unter der questionThreeAnswer-Initialisierung.

private val customerSurveyViewModel: CustomerSurveyViewModel by viewModels()

Stellen Sie sicher, dass Sie die entsprechenden Import-Anweisungen hinzufügen, wenn die IDE Sie dazu auffordert.

Erstellen und ausführen. Starten Sie die Umfrage, geben Sie die erforderlichen E-Mail-Eingaben ein und wählen Sie Ihre Antworten auf die Fragen aus.

Umfragebildschirm mit Antworten

Gut, Sie haben die Umfrage abgeschlossen.

Alle Umfragen mit Datenbankansichten anzeigen Screenshot

Tippen Sie auf die Schaltfläche UMFRAGEN ANSEHEN… ups, das macht noch nichts. Keine Sorge, das werden Sie bald beheben.

Im nächsten Abschnitt erfahren Sie, wie Sie Ihre erste DatabaseView erstellen.

Erstellen einer Datenbankansicht

Um eine Ansicht zu erstellen, fügen Sie eine @DatabaseView-Anmerkung zu einer Klasse oder Datenklasse hinzu. Beginnen Sie damit, zu customersurveys/SurveyListItem.kt zu navigieren. Dies ist eine versiegelte Klasse mit einigen Datenklassen, die Sie in diesem Tutorial verwenden können.

Fügen Sie am Ende von SurveyListItem, direkt unter QuestionOneSadView, Folgendes hinzu:

data class HappyBreakFastView( override val email: String) : SurveyListItem()

Diese Datenklasse überschreibt die E-Mail-Variable aus SurveyListItem und erbt von der Klasse – das heißt, sie ist ein Subtyp von SurveyListItem.

Nach dem Erstellen dieser Datenklasse fügen Sie @DatabaseView mit einer SELECT-Abfrage hinzu, um alle E-Mail-IDs aus der Tabelle „CustomerSurvey“ abzurufen, in der „Mahlzeit“ auf „Frühstück“ eingestellt ist, direkt über der Datenklasse HappyBreakFastView. Ihre Anmerkung sollte wie folgt aussehen:

@DatabaseView("SELECT CustomerSurvey.email FROM CustomerSurvey WHERE CustomerSurvey.meal = 'Breakfast'")

Ein paar Dinge zur Abfrage innerhalb der Anmerkung:

  • Die Abfrage funktioniert wie jede andere Abfrage, die Sie in Room geschrieben haben.
  • Sie müssen alle Felder abfragen, die Sie in Ihrer Datenklasse haben, wenn Sie die Abfrage schreiben. In diesem Fall brauchen Sie nur die E-Mail. Sie verwenden SELECT CustomerSurvey.email From..., um die E-Mail von CustomerSurvey.
abzurufen. Hinweis: In diesem Lernprogramm bleiben die Ansichten und die Entität innerhalb von SurveyListItem, um Wiederholungen zu vermeiden und den Code leichter lesbar zu machen. Sie müssen Ihre Ansichten nicht immer in einer versiegelten Klasse unterordnen; sie können auch in einer eigenen Datei oder Klasse untergebracht werden.

Glückwunsch, Sie haben Ihre erste Ansicht erstellt! Als Nächstes werden Sie sehen, wie Sie die Ansicht in Ihren DAO-Abfragen verwenden können.

Verwendung von Raumdatenbankansichten in DAO-Abfragen

Zuerst werden Sie HappyBreakFastView in views in die @Database der App einfügen.

Navigieren Sie zu database/AppDatabase.kt und fügen Sie innerhalb von views SurveyListItem.HappyBreakFastView::class hinzu. Ihre aktualisierte @Database-Anmerkung sollte wie folgt aussehen:

@Database(entities = , version = 2, exportSchema = false, views = )

Beachten Sie, dass die version = 2. Sie müssen die Datenbankversion jedes Mal aktualisieren, wenn Sie eine view in der AppDatabase hinzufügen – andernfalls wird Ihre App abstürzen. In diesem Fall haben Sie die Version auf 2 aktualisiert. Synchronisieren Sie gradle, um alle diese Änderungen anzuwenden.

Nächste navigieren Sie zu customers/CustomerSurveysDao.kt und fügen Sie direkt unter getQuestionOneSadView() den folgenden Code hinzu:

@Query("SELECT * FROM HappyBreakFastView")fun getHappyBreakFastCustomers():LiveData<List<SurveyListItem.HappyBreakFastView>>

Diese Methode holt alle Kunden, die mit irgendeinem Aspekt der Umfrage zufrieden waren, aus dem Restaurant. Um es genauer zu erklären:

  • Zunächst verwenden Sie HappyBreakFastView wie in einer normalen Abfrage.
  • Sie rufen diese Methode in CustomerSurveyRepo auf, um eine Liste aller Kunden zu erhalten, die auf eine der Fragen mit Gut geantwortet haben. Beachten Sie, dass der Rückgabetyp der Methode eine Liste LiveData vom Typ SurveyListItem.HappyBreakFastView ist, die ein beobachtbarer Variablenhalter ist.

Nun haben Sie eine view und die Methode zur Abfrage der Liste der Kunden, die mit einer positiven Antwort geantwortet haben, in CustomerSurveysDao erstellt. Im nächsten Abschnitt erfahren Sie, wie Sie diese Methode von der Repository-Klasse aus aufrufen können.

Daten mit einer DatabaseView abrufen

Navigieren Sie zu customersurveys/CustomerSurveyRepo.kt und fügen Sie die folgende Methode direkt unter getQuestionOneSadView() ein:

fun getHappyBreakFastCustomers() : LiveData<List<SurveyListItem.HappyBreakFastView>> { return customerSurveysDao.getHappyBreakFastCustomers()}

Diese Methode ruft getHappyBreakFastCustomers() von CustomerSurveysDao aus auf, um die Daten von Room zu erhalten. Ihr Rückgabetyp ist LiveData, was es dem Aufrufer dieser Methode ermöglicht, alle Änderungen in den Daten zu beobachten.

Als Nächstes fügst du einen Aufruf von getHappyBreakFastCustomers() in CustomerSurveyViewModel hinzu. Sie ist für die Anzeige der Daten in der Ansicht verantwortlich – die in diesem Fall nicht DatabaseView, sondern AllSurveysFragment ist.

Navigieren Sie zu customersurveys/CustomerSurveyViewModel.kt und fügen Sie den folgenden Code hinzu:

val happyBreakfastCustomers : LiveData<List<SurveyListItem.HappyBreakFastView>> by lazy { customerSurveyRepo.getHappyBreakFastCustomers()}

Diese Variable erhält ihren Wert durch den Aufruf von getHappyBreakFastCustomers() aus CustomerSurveyRepo. Es gibt ein by lazy{}, damit Sie die Daten nicht sofort laden, sondern erst, wenn auf die Variable zum ersten Mal zugegriffen wird.

Als Nächstes aktualisieren Sie die Benutzeroberfläche, damit sie die Daten anzeigen kann.

Anzeigen der Daten auf der Benutzeroberfläche

Navigieren Sie zu allsurveys/AllSurveysFragment.kt und fügen Sie den folgenden Code am unteren Ende der Klasse hinzu:

private fun getHappyBreakfastCustomers() { customerSurveyViewModel.happyBreakfastCustomers.observe(viewLifecycleOwner, Observer { customerSurveyList -> if (customerSurveyList.isEmpty()) { layoutEmptyView.visibility = View.VISIBLE rvReviews.visibility = View.GONE } else { layoutEmptyView.visibility = View.GONE rvReviews.visibility = View.VISIBLE initView(customerSurveyList) } })}private fun initView(customerSurveySurveyList: List<SurveyListItem.HappyBreakFastView>) { val customerSurveysAdapter = CustomerSurveysAdapter(customerSurveySurveyList) rvReviews.adapter = customerSurveysAdapter}

Um zu erklären, was der Code tut:

  • Zuerst ruft er happyBreakfastCustomers auf und beobachtet seinen Wert.
  • Innerhalb des Observe-Lambdas gibt es eine Prüfung, um zu sehen, ob customerSurveyList null ist oder nicht. Wenn die Liste null ist, setzen Sie die Meldung „Keine Umfragen gefunden!“ von TextView auf sichtbar und blenden RecyclerView aus. Wenn es nicht null ist, setzen Sie die Sichtbarkeit von TextView auf GONE und zeigen RecyclerView an. Außerdem rufen Sie initView(customerSurveyList) mit dem customerSurveyList-Wert aus CustomerSurveyViewModel auf.
  • initView(customerSurveySurveyList: List) initialisiert CustomerSurveysAdapter mit customerSurveyList und setzt den Adapter für RecyclerView auf CustomerSurveysAdapter, der nun die Liste der Umfragen auf der Benutzeroberfläche anzeigt.

Die IDE wird Sie auffordern, den SurveyListItem-Import hinzuzufügen. Wenn dies nicht der Fall ist, fügen Sie diesen Import hinzu:

import com.raywenderlich.android.customersurveys.customersurveys.SurveyListItem

Nachdem Sie die Daten in der Benutzeroberfläche angezeigt haben, sind nur noch wenige Schritte erforderlich, bis alles perfekt funktioniert.

Als Nächstes fügen Sie den Code hinzu, der das Abrufen von Daten aus Room in Abhängigkeit von der im Dropdown-Menü der Benutzeroberfläche, d. h. dem Spinner-Widget, ausgewählten Option behandelt.

Daten für die verschiedenen Ansichten abrufen

Fügen Sie das folgende Codestück direkt unter onCreate in AllSurveysFragment.kt::

private fun spinnerListener() { filterSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onNothingSelected(parent: AdapterView<*>?) {} override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { when (position) { 0 -> resetState() 1 -> getAllCustomerSurveys() 2 -> getHappyBreakfastCustomers() 3 -> getSadDinnerCustomers() 4 -> getAverageLunchCustomers() 5 -> getQuestionOneSadCustomers() } } }}

Das obige Codestück setzt onItemSelectedListener auf filterSpinner und überschreibt zwei Methoden: onNothingSelected und onItemSelected. Sie wollen nichts tun, wenn nichts ausgewählt ist, also bleibt onNothingSelected leer. Sie wollen aber darauf reagieren, wenn ein Element ausgewählt wird, also müssen Sie onItemSelected implementieren.

onItemSelected hat einen when-Ausdruck, der je nach der in filterSpinner ausgewählten Option verschiedene Methoden aufruft. Diese Methoden sind ähnlich wie getHappyBreakfastCustomers(), aber sie rufen Daten mit einem anderen DatabaseView ab.

Stellen Sie sicher, dass Sie die Importe hinzufügen, wenn die IDE Sie dazu auffordert.

Fügen Sie schließlich einen Aufruf von spinnerListener() innerhalb von onViewCreated, direkt nach setupSpinner(), wie unten gezeigt, hinzu:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupSpinner() // Added spinnerListener()}

Nun, da Sie alles zum Abrufen der Umfragen vorbereitet haben, besteht Ihr nächster Schritt darin, den Code zum Navigieren zu AllSurveysFragment hinzuzufügen.

Navigieren zu allen Umfragen

Dies ist der letzte Schritt, den Sie benötigen, um die Ansichten in Aktion zu sehen.

Navigieren Sie zu completedsurvey/SurveyCompletedFragment.kt und entkommentieren Sie den Code in btnViewSurveys. Ihr Endergebnis wird wie folgt aussehen:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) btnViewSurveys.setOnClickListener { findNavController() .navigate(R.id.action_surveyCompletedFragment_to_allSurveysFragment) }}

Hier setzen Sie einfach den Click-Listener für die Schaltfläche VIEW SURVEYS und navigieren zu AllSurveysFragment.

Nachdem Sie den Code entkommentiert haben, werden Sie von der IDE aufgefordert, findNavController() zu importieren. Importieren Sie einfach die erforderliche.

Erstellen Sie eine Umfrage, führen Sie sie aus und starten Sie sie, beantworten Sie dann die Fragen und senden Sie sie ab. Abschließend sehen Sie sich alle Umfragen an, wo Sie alle Daten abrufen können, die von der Option abhängen, die Sie auf dem Spinner ausgewählt haben.

Spinner-Optionen in der App
Durchschnittlich zufriedene Kunden werden in einer Datenbankansicht aufgelistet
Glückliche Dinner-Kunden werden in einer Datenbankansicht nicht gefunden

Glückwunsch! Sie haben Ihr Erlebnis im The View Restaurant beendet. Hoffentlich hast du gut gegessen, eine tolle Aussicht gesehen und gelernt, was DatabaseViews sind.

Wo geht’s weiter?

Lade das fertige Projekt herunter, indem du die Schaltfläche „Materialien herunterladen“ oben oder unten im Tutorial verwendest.

Weitere Informationen über die Funktionen von Room findest du in der offiziellen Dokumentation von Android.

Wir hoffen, dass dir dieses Tutorial über Room Database Views gefallen hat. Wenn Sie Fragen, Kommentare oder tolle Modifikationen zu dieser Projekt-App haben, nehmen Sie bitte an der Forumsdiskussion unten teil.

raywenderlich.com Weekly

Der Newsletter von raywenderlich.com ist der einfachste Weg, um über alles, was Sie als Mobilentwickler wissen müssen, auf dem Laufenden zu bleiben.

Holen Sie sich eine wöchentliche Zusammenfassung unserer Tutorials und Kurse und erhalten Sie als Bonus einen kostenlosen vertiefenden E-Mail-Kurs!

Durchschnittsbewertung

4.8/5

Bewertung für diesen Inhalt hinzufügen

Anmelden, um eine Bewertung hinzuzufügen

10 Bewertungen

Leave a Reply