Databasevisninger med Room til Android

Room er et abstraktionslag over SQLite, som Google har pakket som et AndroidX-bibliotek, og som Google også anbefaler. Siden version 2.1 har Room givet mulighed for at tilføje Database Views, også kendt som gemte forespørgsler.

Nogle af de gode grunde til at bruge Database Views vil være:

  • De gør det nemt for dig at skrive komplekse forespørgsler og bruge dem i DAO-forespørgsler (Data Access Object).
  • Du kan kun spørge om de felter, du har brug for, i stedet for at skulle gennemgå alle felterne i en tabel.

I denne vejledning skal du bygge en kundeundersøgelsesapp, som lader en restaurants kunder afgive feedback, og derefter gemmer denne feedback i Room managed database. I løbet af processen lærer du følgende:

  • Hvad er en databasevisning?
  • Hvordan oprettes databasevisninger?
  • Hvordan bruges de til at forenkle skrivning af SELECT-forespørgsler
Bemærk: Denne vejledning forudsætter, at du har erfaring med at udvikle til Android i Kotlin, og at du har arbejdet med Room før. Hvis du ikke er bekendt med Room, skal du tage et kig på vores tutorial om datapersistens med Room.

Denne tutorial bruger også Coroutines med Room. Hvis du vil vide mere, kan du læse vores tutorial om Coroutines med Room Persistence Library.

Gå i gang

Download startprojektet ved at klikke på knappen Download materialer øverst eller nederst i denne tutorial.

Udpak ZIP-filen, og åbn startprojektet i Android Studio 4.0 eller nyere ved at vælge Åbn et eksisterende Android Studio-projekt på velkomstskærmen.

Når Gradle-synkroniseringen er afsluttet, skal du udforske projektstrukturen. Projektet følger MVVM-arkitekturen, så lignende funktionaliteter er under én pakke. Gør dig bekendt med de tilstedeværende pakker – du vil bruge dem i denne tutorial.

Byg op, og kør. Du vil se en simpel skærm med en velkomstmeddelelse, et billede og en START SURVEY-knap.

Skærmbilledet Start Survey i appen Customer Surveys

Tryk på knappen START SURVEY (Start undersøgelse). I forbindelse med denne vejledning kan du ignorere, at du ikke har spist et måltid på restauranten :]

Den næste skærm er undersøgelsesskærmen. Den har et e-mailindtastningsfelt, radioknapper til at vælge det måltid, som du bedømmer, og tre spørgsmål. Hvert spørgsmål har knapperne Godt, Gennemsnitligt og Dårligt under sig, så brugeren kan vurdere sin tilfredshed.

Kundeundersøgelsesappens undersøgelsesskærm med spørgsmål og mulige vurderinger

Du kan også se knappen INDLÆG UNDERSØGELSE. Tryk på den, og du vil se en skål, der siger, at det ikke er tid til at gennemføre undersøgelsen endnu. Bare rolig, det retter du op på i løbet af denne vejledning.

Du er nu blevet budt velkommen til The View Restaurant, hvor du kan se fantastiske udsigter over naturen, smage deres lækre måltider og bedømme din tilfredshed. Mens du er i gang, lærer du også om Room Database Views.

Anvendelse af databasevisninger

Tænk på en tabel, der har ekstra funktionalitet af færdigpakkede SELECT-forespørgsler for nemheds skyld. Room version 2.1 og højere kalder disse som en databasevisning og giver en annotation med samme navn, dvs. @DatabaseView.

Ved hjælp af denne annotation kan du markere en klasse til at opføre sig som en Database View. Dette giver dig mulighed for at knytte en forespørgsel til klassen som nedenfor:

@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}

Du kan derefter bruge denne klasse i din DAO til at forespørge data på samme måde, som du ville gøre med en klasse, der er markeret som en Entity, dvs. en tabel i en database.

En DAO hjælper dig med at få adgang til data fra din app’s database. Den indeholder typisk CUD-metoderne (Create, Update og Delete) og kan også indeholde andre metoder, der kan være nødvendige for læse- og skriveadgang til databasen.

Forholdet mellem Database Views og databasen svarer til forholdet mellem entiteter og databasen. Du vil se nærmere på disse relationer næste gang.

Sammenligning af en databasevisning og en entitet

Klasser annoteret med @DatabaseView svarer til Entity-klasser. Sådan er det:

  • Både kan bruge SELECT FROM i DAO-forespørgsler.
  • Database Views og Entitys kan begge bruge @ColumnInfo, som giver dig mulighed for at tilpasse de kolonneoplysninger, der er knyttet til et felt.
  • De kan begge bruge @Embedded, som giver et felt mulighed for at have indlejrede felter, som forespørgsler kan henvise direkte til.

Selv om der er mange ligheder mellem de to, er der også forskelle mellem DatabaseViews og Entitys:

  • Du kan bruge INSERT, UPDATE og DELETE med en Entity, men ikke med en DatabaseView.
  • Du definerer alle dine visninger i dine apps ved hjælp af views, men du definerer enheder ved hjælp af entities.

Nu da du ved, hvad en DatabaseView er, og hvordan den sammenligner og kontrasterer med en Entity-klasse, er det tid til at bruge den og begynde at indsende undersøgelsen til The View Restaurant.

Indsendelse af undersøgelsen

Dit første skridt er at tilføje logikken til at indsende undersøgelsen og gemme den i Room-databasen, efter at du har trykket på knappen SUBMIT SURVEY.

Navigér til customersurveys/CustomerSurveyFragment.kt, hvor du skal tilføje logikken til indsamling af svarene og lagring af dem i Room. Det gør du ved at erstatte koden i submitSurvey() med denne:

// 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)}

Her er, hvad du gør med denne kode:

  1. Du henter e-mailen fra editEmail og tildeler den til en variabel: email.
  2. Denne tilstandskontrol kalder validateEmail(email), som kontrollerer, om e-mailen er null eller ej. Den returnerer false, hvis det er null. Den kontrollerer også, om den indtastede e-mail er gyldig, og returnerer false, hvis den ikke er det.
  3. Koden inde i if-anvisningen udføres, når validateEmail(email) returnerer true. meal indeholder den måltidstype, som brugeren har valgt fra radiogrupperne.
  4. Når du har meals værdi, opretter du SurveyListItem.CustomerSurvey, som indeholder alle oplysninger om undersøgelsen. Den henter værdierne for questionOneAnswer, questionTwoAnswer og questionThreeAnswer fra toggleButtonListeners(), som har lyttere til det formål.
  5. Her gemmer du customerSurvey ved at kalde insertCustomerSurvey(customerSurvey) i CustomerSurveyViewModel, som håndterer logikken for at gemme til Room.
  6. Du navigerer til SurveyCompletedFragment.

Når du har tilføjet dette, vil du bemærke, at customerSurveyViewModel og findNavController() har røde understregninger. Hvis du vil rette dette, skal du først tilføje CustomerSurveyViewModel-initialiseringen øverst i klassen, lige under questionThreeAnswer-initialiseringen.

private val customerSurveyViewModel: CustomerSurveyViewModel by viewModels()

Sørg for at tilføje de respektive import-statements, når IDE’en beder dig om det.

Byg op, og kør. Start undersøgelsen, indtast den krævede e-mailindtastning, og vælg dine svar på spørgsmålene.

Undersøgelsesskærm med svarene

Godt, du har gennemført undersøgelsen.

Se alle undersøgelser ved hjælp af databasevisninger Screenshot

Tryk på knappen VIEW SURVEYS … Ups, det gør ikke noget endnu. Bare rolig, det løser du snart.

I det næste afsnit lærer du, hvordan du opretter din første DatabaseView.

Skabelse af en databasevisning

For at oprette en visning tilføjer du en @DatabaseView-annotation til en klasse eller dataklasse. Start med at navigere til customersurveys/SurveyListItem.kt. Dette er en forseglet klasse med et par dataklasser, som du kan bruge i denne vejledning.

Underst i SurveyListItem, lige under QuestionOneSadView, tilføjes følgende:

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

Denne dataklasse tilsidesætter e-mail-variablen fra SurveyListItem og arver fra klassen – hvilket betyder, at den er en undertype af SurveyListItem.

Når du har oprettet denne dataklasse, skal du tilføje @DatabaseView med en SELECT-forespørgsel for at hente alle e-mail-id’er fra tabellen CustomerSurvey, hvor meal er indstillet til “Breakfast”, lige over dataklassen HappyBreakFastView. Din annotation skal se således ud:

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

Et par ting at bemærke om forespørgslen inde i annotationen:

  • Spørgslen fungerer som enhver anden forespørgsel, du har skrevet i Room.
  • Du skal anmode om alle de felter, du har i din dataklasse, når du skriver forespørgslen. I dette tilfælde har du kun brug for e-mailen. Du bruger SELECT CustomerSurvey.email From... til at hente e-mailen fra CustomerSurvey.
Bemærk: I denne vejledning beholder du visningerne og entiteten inden for SurveyListItem for at undgå gentagelser og for at gøre koden lettere at læse. Du behøver ikke altid at underklassere dine visninger i en forseglet klasse; de kan også være i deres egen separate fil eller klasse.

Tillykke, du har oprettet din første visning! Nu skal du se, hvordan du kan bruge visningen i dine DAO-forespørgsler.

Brug af rumdatabasevisninger i DAO-forespørgsler

Først skal du inkludere HappyBreakFastView i views i appens @Database.

Navigér til database/AppDatabase.kt, og inden for views skal du tilføje SurveyListItem.HappyBreakFastView::class. Din opdaterede @Database-annotation bør se ud som nedenfor:

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

Bemærk, at version = 2. Du skal opdatere databaseversionen, hver gang du tilføjer en view i AppDatabase – ellers vil din app gå ned. I dette tilfælde har du opdateret versionen til 2. Synkroniser gradle for at anvende alle disse ændringer.

Næst skal du navigere til customers/CustomerSurveysDao.kt, og lige under getQuestionOneSadView() skal du tilføje følgende kode:

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

Denne metode henter alle kunder, der var tilfredse med et hvilket som helst aspekt af undersøgelsen fra restauranten. For at forklare den nærmere:

  • Først bruger du HappyBreakFastView, som du ville gøre i en normal forespørgsel.
  • Du kalder denne metode i CustomerSurveyRepo for at få en liste over alle de kunder, der svarede Godt på et af spørgsmålene. Bemærk, at metodens returtype er en liste LiveData af typen SurveyListItem.HappyBreakFastView, som er en observerbar variabelholder.

Nu har du oprettet en view og metoden til at forespørge listen over kunder, der svarede med et positivt svar i CustomerSurveysDao. I næste afsnit lærer du, hvordan du kalder denne metode fra repository-klassen.

Hentning af data ved hjælp af et databaseView

Navigér til customersurveys/CustomerSurveyRepo.kt, og tilføj følgende metode lige under getQuestionOneSadView():

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

Denne metode kalder getHappyBreakFastCustomers() fra CustomerSurveysDao for at hente dataene fra Room. Dens returneringstype er en LiveData, hvilket gør det muligt for den, der kalder denne metode, at observere eventuelle ændringer i dataene.

Næste gang tilføjer du et kald til getHappyBreakFastCustomers() i CustomerSurveyViewModel. Den er ansvarlig for at vise dataene til visningen – som i dette tilfælde ikke er DatabaseView, men AllSurveysFragment.

Navigér til customersurveys/CustomerSurveyViewModel.kt, og tilføj følgende kode:

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

Denne variabel får sin værdi ved at kalde getHappyBreakFastCustomers() fra CustomerSurveyRepo. Der er en by lazy{}, så du ikke indlæser dataene med det samme, men først når variablen tilgås første gang.

Næst skal du opdatere brugergrænsefladen, så den kan vise dataene.

Visning af data til brugergrænsefladen

Navigér til allsurveys/AllSurveysFragment.kt og tilføj følgende kode nederst i klassen:

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}

For at forklare, hvad koden gør:

  • Først kalder den happyBreakfastCustomers og observerer dens værdi.
  • Inden for observere lambdaen er der en kontrol for at se, om customerSurveyList er null eller ej. Hvis listen er null, indstiller du TextViews meddelelse Ingen undersøgelser fundet! til synlig og skjuler RecyclerView. Hvis den ikke er null, indstiller du TextViews synlighed til GONE og viser RecyclerView. Du kalder også initView(customerSurveyList) med customerSurveyList-værdien fra CustomerSurveyViewModel.
  • initView(customerSurveySurveyList: List) initialiserer CustomerSurveysAdapter med customerSurveyList og indstiller adapteren for RecyclerView til CustomerSurveysAdapter, som nu viser listen over undersøgelser til brugergrænsefladen.

IDE’en beder dig om at tilføje SurveyListItem-import. Hvis den ikke gør det, skal du tilføje denne import:

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

Nu, hvor du har vist dataene til brugergrænsefladen, har du kun et par trin mere, før alt fungerer perfekt.

Næst skal du tilføje den kode, der håndterer hentning af data fra Room afhængigt af den valgte indstilling i dropdown-menuen i brugergrænsefladen, dvs. Spinner-widget.

Hentning af data for de forskellige visninger

Føj følgende kodestykke lige under onCreate i 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() } } }}

Kodestykket ovenfor sætter onItemSelectedListener til filterSpinner og overstyrer to metoder: onNothingSelected og onItemSelected. Du ønsker ikke at gøre noget, når intet er valgt, så onNothingSelected efterlades tomt. Du ønsker at reagere på, når et element er valgt, så du skal implementere onItemSelected.

onItemSelected har et when-udtryk, der kalder forskellige metoder afhængigt af den valgte indstilling i filterSpinner. Disse metoder ligner getHappyBreakfastCustomers(), men de henter data ved hjælp af en anden DatabaseView.

Sørg for, at du tilføjer importen, når IDE’en beder dig om det.

Slutteligt skal du tilføje et kald til spinnerListener() inde i onViewCreated, lige efter setupSpinner(), som vist nedenfor:

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

Nu, hvor du har alt klar til at hente undersøgelserne, er dit næste skridt at tilføje koden til at navigere til AllSurveysFragment.

Navigation til alle undersøgelser

Dette er det sidste trin, du skal bruge for at se visningerne i aktion.

Navigér til completedsurvey/SurveyCompletedFragment.kt, og udkommenter koden inde i btnViewSurveys. Dit endelige resultat vil se således ud:

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

Her indstiller du blot kliklytteren for knappen VIEW SURVEYS og navigerer til AllSurveysFragment.

Når du har udkommenteret koden, vil IDE’en bede dig om at importere findNavController(). Du skal blot importere det nødvendige.

Byg, kør og start en undersøgelse, og besvar derefter spørgsmålene, og indsend dem. Til sidst skal du se Alle undersøgelser, hvor du vil kunne hente alle data afhængigt af den indstilling, du har valgt på spinneren.

Spinnerindstillinger i appen
Liste over gennemsnitligt tilfredse kunder ved hjælp af en databasevisning
Sørgelige middagskunder ikke fundet ved hjælp af en databasevisning

Godt tillykke! Du har afsluttet din oplevelse på The View Restaurant. Forhåbentlig har du fået et godt måltid, set fantastiske udsigter og haft mulighed for at lære, hvad DatabaseViews er.

Hvor skal vi gå hen herfra?

Download det endelige projekt ved at bruge knappen Download materialer øverst eller nederst i vejledningen.

For flere oplysninger om Room-funktionerne kan du læse den officielle dokumentation fra Android.

Vi håber, at du nød denne vejledning om Room Database Views. Hvis du har spørgsmål, kommentarer eller fantastiske ændringer til denne projekt-app, kan du deltage i forumdiskussionen nedenfor.

raywenderlich.com Weekly

Raywenderlich.com-nyhedsbrevet er den nemmeste måde at holde sig opdateret om alt, hvad du har brug for at vide som mobiludvikler.

Få en ugentlig oversigt over vores tutorials og kurser, og modtag et gratis dybdegående e-mail-kursus som en bonus!

Gennemsnitlig bedømmelse

4.8/5

Føj en bedømmelse til dette indhold

Log ind for at tilføje en bedømmelse

10 bedømmelser

Leave a Reply