Viste di database con Room per Android
Room è uno strato di astrazione sopra SQLite che Google ha confezionato come libreria AndroidX e che raccomanda anche. Dalla versione 2.1, Room offre la possibilità di aggiungere Database Views, note anche come query memorizzate.
Alcuni dei buoni motivi per utilizzare le Database Views sarebbero:
- Rendono facile per voi scrivere query complesse e utilizzarle in query Data Access Object (DAO).
- Puoi interrogare solo i campi di cui hai bisogno, piuttosto che dover passare attraverso tutti i campi di una tabella.
In questo tutorial, costruirai un’applicazione Customer Surveys che permette ai clienti di un ristorante di lasciare un feedback, poi salva il feedback nel database gestito dalla Room. Durante il processo imparerai quanto segue:
- Cos’è una vista di database?
- Come creare viste di database?
- Come usarle per semplificare la scrittura di query SELECT
Questo tutorial usa anche le Coroutine con Room. Per saperne di più, leggete il nostro tutorial Coroutines With Room Persistence Library.
Iniziare
Scaricate il progetto iniziale facendo clic sul pulsante Scarica materiali all’inizio o alla fine di questo tutorial.
Estraete il file ZIP e aprite il progetto iniziale in Android Studio 4.0 o successivo selezionando Open an existing Android Studio project dalla schermata di benvenuto.
Una volta completata la sincronizzazione con Gradle, esplorate la struttura del progetto. Il progetto segue l’architettura MVVM, quindi funzionalità simili sono sotto un unico pacchetto. Familiarizza con i pacchetti presenti – li userai in questo tutorial.
Costruisci ed esegui. Vedrai una semplice schermata con un messaggio di benvenuto, un’immagine e un pulsante START SURVEY.
Tocca il pulsante INIZIA L’INDAGINE. Per lo scopo di questo tutorial, puoi ignorare il fatto che non hai mangiato al ristorante. :]
La prossima schermata è quella del sondaggio. Ha un campo di input e-mail, pulsanti radio per scegliere il pasto che stai valutando e tre domande. Ogni domanda ha i pulsanti Buono, Medio e Cattivo sotto di loro, in modo che l’utente possa valutare la propria soddisfazione.
Vedrai anche il pulsante SUBMIT SURVEY. Toccalo e vedrai un brindisi che dice che non è ancora il momento di fare il sondaggio. Non preoccuparti, lo risolverai nel corso di questo tutorial.
Ti è stato dato il benvenuto al The View Restaurant, dove potrai vedere incredibili viste sulla natura, assaggiare i loro deliziosi piatti e valutare la tua soddisfazione. Già che ci sei, imparerai anche le visualizzazioni del database di Room.
Usare le visualizzazioni del database
Considera una tabella che ha funzionalità extra di query SELECT preconfezionate per comodità. Le versioni 2.1 e superiori di Room le chiamano viste di database e forniscono un’annotazione con lo stesso nome, cioè @DatabaseView
.
Utilizzando questa annotazione potete marcare una classe per comportarsi come una Vista del database. Questo vi permetterà di allegare una query alla classe, come sotto:
@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}
Potete quindi usare questa classe nel vostro DAO per interrogare i dati nello stesso modo in cui fareste con una classe contrassegnata come Entità, cioè Tabella in un database.
Un DAO vi aiuta ad accedere ai dati dal database della vostra applicazione. Tipicamente contiene i metodi CUD (Create, Update and Delete) e può anche contenere altri metodi che possono essere necessari per l’accesso in lettura e scrittura al database.
La relazione tra le Viste del database e il database è simile alla relazione tra entità e il database. Daremo un’occhiata più approfondita a queste relazioni dopo.
Confronto tra una vista di database e un’entità
Le classi annotate con @DatabaseView
sono simili alle classi Entity
. Ecco come:
- Entrambe possono usare SELECT FROM nelle query DAO.
-
Database View
s eEntity
s possono entrambe usare@ColumnInfo
, che permette di personalizzare le informazioni delle colonne associate ad un campo. - Possono entrambe usare
@Embedded
, che permette ad un campo di avere campi annidati che le query possono referenziare direttamente.
Mentre ci sono molte somiglianze tra i due, ci sono anche differenze tra DatabaseView
e Entity
:
- Puoi usare INSERT, UPDATE e DELETE con un
Entity
, ma non con unDatabaseView
. - Definirai tutte le tue viste nelle tue applicazioni usando
views
, ma definisci le entità usandoentities
.
Ora che sai cos’è un DatabaseView
e come si confronta e contrasta con una classe Entity
, è ora di usarlo e iniziare a presentare il sondaggio per The View Restaurant.
Invio dell’indagine
Il tuo primo passo è aggiungere la logica per inviare l’indagine e salvarla nel database di Room dopo aver toccato il pulsante SUBMIT SURVEY.
Passa a customersurveys/CustomerSurveyFragment.kt, dove aggiungerai la logica per raccogliere le risposte e salvarle in Room. Fallo sostituendo il codice in submitSurvey()
con questo:
// 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)}
Ecco cosa stai facendo con questo codice:
- Prendi l’email da
editEmail
e assegnala a una variabile:email
. - Questo controllo di condizione chiama
validateEmail(email)
, che controlla se l’email ènull
o no. Restituiscefalse
se ènull
. Controlla anche se l’email inserita è valida e restituiscefalse
se non lo è. - Il codice dentro l’istruzione
if
viene eseguito quandovalidateEmail(email)
restituiscetrue
.meal
tiene il tipo di pasto che l’utente ha selezionato dai gruppi radio. - Una volta che avete il valore di
meal
, createSurveyListItem.CustomerSurvey
, che ha tutte le informazioni sul sondaggio. Esso estrae i valori diquestionOneAnswer
,questionTwoAnswer
equestionThreeAnswer
datoggleButtonListeners()
, che ha degli ascoltatori per questo scopo. - Qui si salva
customerSurvey
chiamandoinsertCustomerSurvey(customerSurvey)
inCustomerSurveyViewModel
, che gestisce la logica per salvare in Room. - Passa a SurveyCompletedFragment.
Dopo aver aggiunto questo, noterai che customerSurveyViewModel
e findNavController()
hanno delle sottolineature rosse. Per risolvere questo problema, aggiungete prima l’inizializzazione CustomerSurveyViewModel
all’inizio della classe, appena sotto l’inizializzazione questionThreeAnswer
.
private val customerSurveyViewModel: CustomerSurveyViewModel by viewModels()
Assicuratevi di aggiungere le rispettive dichiarazioni di importazione quando l’IDE ve lo chiede.
Costruisci ed esegui. Avvia il sondaggio, inserisci l’email richiesta e seleziona le tue risposte alle domande.
Bene, hai completato il sondaggio.
Tocca il pulsante VIEW SURVEYS… oops, non fa ancora niente. Non preoccuparti, lo risolverai presto.
Nella prossima sezione, imparerai come creare il tuo primo DatabaseView
.
Creazione di una vista sul database
Per creare una vista, aggiungerai un’annotazione @DatabaseView
a una classe o a una classe dati. Iniziate navigando verso customersurveys/SurveyListItem.kt. Questa è una classe sigillata con un paio di classi di dati da usare in questo tutorial.
In fondo a SurveyListItem
, appena sotto QuestionOneSadView
, aggiungete quanto segue:
data class HappyBreakFastView( override val email: String) : SurveyListItem()
Questa classe di dati sovrascrive la variabile email da SurveyListItem
ed eredita dalla classe – cioè è un sottotipo di SurveyListItem
.
Dopo aver creato questa classe di dati, aggiungete @DatabaseView
con una query SELECT per recuperare tutti gli id delle e-mail dalla tabella CustomerSurvey dove il pasto è impostato su “Breakfast”, appena sopra la classe di dati HappyBreakFastView
. La tua annotazione dovrebbe essere simile a questa:
@DatabaseView("SELECT CustomerSurvey.email FROM CustomerSurvey WHERE CustomerSurvey.meal = 'Breakfast'")
Alcune cose da notare sulla query all’interno dell’annotazione:
- La query funziona come qualsiasi altra query che hai scritto in Room.
- Devi richiedere tutti i campi che hai nella tua classe dati mentre scrivi la query. In questo caso, avete bisogno solo dell’email. Usa
SELECT CustomerSurvey.email From...
per ottenere l’e-mail daCustomerSurvey
.
Congratulazioni, hai creato la tua prima vista! Ora vedrai come puoi usare la vista nelle tue query DAO.
Using Room Database Views in DAO Queries
Primo, includerai HappyBreakFastView
in views
nel @Database
dell’app.
Passa a database/AppDatabase.kt e, dentro views
, aggiungi SurveyListItem.HappyBreakFastView::class
. La tua annotazione @Database
aggiornata dovrebbe apparire come segue:
@Database(entities = , version = 2, exportSchema = false, views = )
Nota che il version = 2
. Devi aggiornare la versione del database ogni volta che aggiungi un view
nell’AppDatabase – altrimenti la tua app andrà in crash. In questo caso, hai aggiornato la versione a 2. Sincronizza gradle per applicare tutte queste modifiche.
Poi, naviga verso customers/CustomerSurveysDao.kt e, proprio sotto getQuestionOneSadView()
, aggiungi il seguente codice:
@Query("SELECT * FROM HappyBreakFastView")fun getHappyBreakFastCustomers():LiveData<List<SurveyListItem.HappyBreakFastView>>
Questo metodo ottiene dal ristorante tutti i clienti che sono rimasti soddisfatti di qualsiasi aspetto del sondaggio. Per spiegarlo più dettagliatamente:
- Primo, usate
HappyBreakFastView
come fareste in una normale query. - Chiamate questo metodo in
CustomerSurveyRepo
per ottenere una lista di tutti i clienti che hanno risposto a qualsiasi domanda con Buono. Notate che il tipo di ritorno del metodo è una listaLiveData
di tipoSurveyListItem.HappyBreakFastView
, che è un titolare di variabile osservabile.
Ora, avete creato un view
e il metodo per interrogare la lista dei clienti che hanno risposto con una risposta positiva in CustomerSurveysDao
. Nella prossima sezione, imparerai come chiamare questo metodo dalla classe repository.
Fetching Data Using a DatabaseView
Passa a customersurveys/CustomerSurveyRepo.kt e aggiungi il seguente metodo appena sotto getQuestionOneSadView()
:
fun getHappyBreakFastCustomers() : LiveData<List<SurveyListItem.HappyBreakFastView>> { return customerSurveysDao.getHappyBreakFastCustomers()}
Questo metodo chiama getHappyBreakFastCustomers()
da CustomerSurveysDao
per ottenere i dati da Room. Il suo tipo di ritorno è un LiveData
, che permette a chi chiama questo metodo di osservare qualsiasi cambiamento nei dati.
Poi, aggiungerai una chiamata a getHappyBreakFastCustomers()
in CustomerSurveyViewModel
. È responsabile della visualizzazione dei dati alla vista – che, in questo caso, non è DatabaseView
ma AllSurveysFragment.
Passa a customersurveys/CustomerSurveyViewModel.kt e aggiungi il seguente codice:
val happyBreakfastCustomers : LiveData<List<SurveyListItem.HappyBreakFastView>> by lazy { customerSurveyRepo.getHappyBreakFastCustomers()}
Questa variabile ottiene il suo valore chiamando getHappyBreakFastCustomers()
da CustomerSurveyRepo
. C’è un by lazy{}
in modo da non caricare i dati immediatamente, ma piuttosto quando si accede per la prima volta alla variabile.
Poi, aggiornerai l’UI in modo che possa visualizzare i dati.
Visualizzazione dei dati nell’UI
Passa a allsurveys/AllSurveysFragment.kt e aggiungi il seguente codice in fondo alla classe:
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}
Per spiegare cosa fa il codice:
- Prima di tutto, chiama
happyBreakfastCustomers
e osserva il suo valore. - Dentro la lambda observe, c’è un controllo per vedere se customerSurveyList è
null
o no. Se la lista ènull
, si imposta il messaggio No surveys found! diTextView
su visible e si nascondeRecyclerView
. Se non ènull
, imposti la visibilità diTextView
su GONE e mostriRecyclerView
. Chiamate ancheinitView(customerSurveyList)
con il valorecustomerSurveyList
diCustomerSurveyViewModel
. -
initView(customerSurveySurveyList: List)
inizializzaCustomerSurveysAdapter
concustomerSurveyList
e imposta l’adattatore perRecyclerView
aCustomerSurveysAdapter
, che ora visualizza la lista dei sondaggi nell’UI.
L’IDE vi chiederà di aggiungere l’importazione SurveyListItem
. Se non lo fa, aggiungi questa importazione:
import com.raywenderlich.android.customersurveys.customersurveys.SurveyListItem
Ora che hai visualizzato i dati nell’interfaccia utente, hai solo pochi altri passaggi prima che tutto funzioni perfettamente.
Prossimo, aggiungerai il codice che gestisce il recupero dei dati da Room a seconda dell’opzione selezionata sul dropdown nell’interfaccia utente, cioè il widget Spinner.
Fetching Data for the Different Views
Aggiungi il seguente pezzo di codice appena sotto 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() } } }}
Il pezzo di codice sopra imposta onItemSelectedListener
a filterSpinner
e sovrascrive due metodi: onNothingSelected
e onItemSelected
. Non volete fare nulla quando non è selezionato nulla, quindi onNothingSelected
è lasciato vuoto. Vuoi reagire a quando un elemento è selezionato, quindi hai bisogno di implementare onItemSelected
.
onItemSelected
ha un’espressione when
che chiama diversi metodi a seconda dell’opzione selezionata in filterSpinner
. Questi metodi sono simili a getHappyBreakfastCustomers()
, ma recuperano i dati usando un diverso DatabaseView
.
Assicurati di aggiungere le importazioni quando l’IDE te lo chiede.
Infine, aggiungi una chiamata a spinnerListener()
dentro onViewCreated
, subito dopo setupSpinner()
, come mostrato sotto:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupSpinner() // Added spinnerListener()}
Ora che hai tutto pronto per recuperare le indagini, il tuo prossimo passo è aggiungere il codice per navigare verso AllSurveysFragment
.
Navigare verso tutti i sondaggi
Questo è l’ultimo passo di cui hai bisogno per vedere le viste in azione.
Vai a completedsurvey/SurveyCompletedFragment.kt e decommenta il codice dentro btnViewSurveys
. Il tuo risultato finale sarà simile a questo:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) btnViewSurveys.setOnClickListener { findNavController() .navigate(R.id.action_surveyCompletedFragment_to_allSurveysFragment) }}
Qui, stai semplicemente impostando l’ascoltatore di click per il pulsante VIEW SURVEYS e navigando verso AllSurveysFragment
.
Una volta decommentato il codice, l’IDE ti chiederà di importare findNavController()
. Importa semplicemente il richiesto.
Costruisci, esegui e avvia un sondaggio, poi rispondi alle domande e inviale. Infine, visualizza Tutti i sondaggi, dove sarai in grado di recuperare tutti i dati a seconda dell’opzione che hai selezionato sullo spinner.
Congratulazioni! Hai finito la tua esperienza al ristorante The View. Speriamo che tu abbia mangiato bene, che tu abbia visto una vista fantastica e che tu abbia avuto la possibilità di imparare cosa sono le DatabaseViews.
Dove andare da qui?
Scarica il progetto finale usando il pulsante Scarica materiali in cima o in fondo al tutorial.
Per maggiori informazioni sulle caratteristiche di Room, controlla la documentazione ufficiale di Android.
Speriamo che questo tutorial di Room Database Views ti sia piaciuto. Se hai domande, commenti o fantastiche modifiche a questo progetto di app, unisciti alla discussione sul forum qui sotto.
raywenderlich.com Weekly
La newsletter di raywenderlich.com è il modo più semplice per rimanere aggiornati su tutto ciò che devi sapere come sviluppatore mobile.
Ottieni un digest settimanale dei nostri tutorial e corsi, e ricevi un corso di approfondimento gratuito via email come bonus!
Voto medio
4.8/5
Aggiungi un voto per questo contenuto
Accedi per aggiungere un voto
Leave a Reply