Databázové pohledy pomocí Room pro Android

Room je abstrakční vrstva nad SQLite, kterou Google přibalil jako knihovnu pro AndroidX a také ji doporučuje. Od verze 2.1 nabízí Room možnost přidávat Databázové pohledy, známé také jako uložené dotazy.

Několik dobrých důvodů, proč používat Databázové pohledy, by mohlo být:

  • Usnadňují psaní složitých dotazů a jejich použití v dotazech DAO (Data Access Object).
  • Můžete se dotazovat pouze na pole, která potřebujete, místo toho, abyste museli procházet všechna pole v tabulce.

V tomto tutoriálu budete vytvářet aplikaci Průzkumy zákazníků, která umožňuje zákazníkům restaurace zanechat zpětnou vazbu, a poté tuto zpětnou vazbu uloží do databáze Spravovaná místnost. Během tohoto procesu se naučíte následující:

  • Co je to databázový pohled?
  • Jak vytvářet databázové pohledy?
  • Jak je používat pro zjednodušení psaní dotazů SELECT
Poznámka: Tento tutoriál předpokládá, že máte zkušenosti s vývojem pro Android v Kotlinu a že jste již dříve pracovali s Roomem. Pokud Room neznáte, podívejte se na náš tutoriál Persistence dat s Roomem

Tento tutoriál také používá Coroutines s Roomem. Chcete-li se dozvědět více, přečtěte si náš tutoriál Coroutines With Room Persistence Library.

Začínáme

Stáhněte si startovací projekt kliknutím na tlačítko Download Materials (Stáhnout materiály) v horní nebo dolní části tohoto tutoriálu.

Extrahujte soubor ZIP a otevřete startovací projekt v aplikaci Android Studio 4.0 nebo novější volbou Open an existing Android Studio project (Otevřít existující projekt Android Studia) na úvodní obrazovce.

Po dokončení synchronizace Gradle prozkoumejte strukturu projektu. Projekt se řídí architekturou MVVM, takže podobné funkce jsou pod jedním balíkem. Seznamte se s přítomnými balíčky – budete je používat v tomto tutoriálu.

Sestavte a spusťte. Zobrazí se jednoduchá obrazovka s uvítací zprávou, obrázkem a tlačítkem START SURVEY.

Ekranáž START SURVEY aplikace Customer Surveys

Klepněte na tlačítko START SURVEY. Pro účely tohoto návodu můžete ignorovat skutečnost, že jste v restauraci nejedli :]

Následující obrazovka je obrazovka průzkumu. Obsahuje pole pro zadání e-mailu, přepínače pro výběr jídla, které hodnotíte, a tři otázky. Každá otázka má pod sebou tlačítka Dobrý, Průměrný a Špatný, takže uživatel může ohodnotit svou spokojenost.

Ekran průzkumu aplikace Průzkumy zákazníků s otázkami a možnými hodnoceními

Zobrazí se také tlačítko ODESLAT PRŮZKUM. Klepněte na něj a zobrazí se přípitek, který říká, že ještě není čas na provedení průzkumu. Nebojte se, v průběhu tohoto návodu to napravíte.

Nyní jste byli přivítáni v restauraci The View, kde uvidíte úžasný výhled na přírodu, ochutnáte jejich vynikající jídla a ohodnotíte svou spokojenost. Při tom se také dozvíte o databázových pohledech na místnosti.

Používání databázových pohledů

Považujte za tabulku, která má pro větší pohodlí další funkce předpřipravených dotazů SELECT. Verze Room 2.1 a vyšší je nazývá Database View a poskytuje anotaci se stejným názvem, tedy @DatabaseView.

Pomocí této anotace můžete označit třídu, aby se chovala jako Database View. To vám umožní připojit k této třídě dotaz, jako je tomu níže:

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

Tuto třídu pak můžete použít ve svém DAO k dotazování na data stejným způsobem, jako byste to udělali se třídou označenou jako Entita, tj. tabulka v databázi.

Třída DAO vám pomáhá přistupovat k datům z databáze vaší aplikace. Obvykle obsahuje metody CUD (Create, Update a Delete) a může obsahovat i další metody, které mohou být nezbytné pro přístup ke čtení a zápisu do databáze.

Vztah mezi databázovými pohledy a databází je podobný vztahu mezi entitami a databází. Na tyto vztahy se podíváte hlouběji příště.

Porovnání databázového pohledu a entity

Třídy s anotací @DatabaseView jsou podobné třídám Entity. Takto:

  • Obě mohou používat SELECT FROM v dotazech DAO.
  • Database Views i Entitys mohou používat @ColumnInfo, který umožňuje přizpůsobit informace o sloupci spojeném s polem.
  • Obě mohou používat @Embedded, který umožňuje, aby pole mělo vnořená pole, na která mohou dotazy přímo odkazovat.

Přestože je mezi nimi mnoho podobností, existují také rozdíly mezi DatabaseViews a Entitys:

  • S Entitys můžete použít INSERT, UPDATE a DELETE, ale ne s DatabaseView.
  • Všechny pohledy ve svých aplikacích definujete pomocí views, ale entity definujete pomocí entities.

Teď, když víte, co je DatabaseView a jak se srovnává a liší od třídy Entity, je čas ji použít a začít odesílat dotazník pro The View Restaurant.

Odeslání průzkumu

Vaším prvním krokem je přidat logiku pro odeslání průzkumu a jeho uložení do databáze Room poté, co klepnete na tlačítko SUBMIT SURVEY.

Přejděte na customersurveys/CustomerSurveyFragment.kt, kde přidáte logiku pro sběr odpovědí a jejich uložení do Room. Uděláte to tak, že nahradíte kód v submitSurvey() tímto:

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

Takto postupujete s tímto kódem:

  1. Získáte e-mail z editEmail a přiřadíte jej do proměnné: email.
  2. Tato kontrola podmínky volá validateEmail(email), který kontroluje, zda je e-mail null nebo ne. Pokud je null, vrátí false. Také kontroluje, zda je zadaný e-mail platný, a pokud není, vrátí false.
  3. Kód uvnitř příkazu if se provede, když validateEmail(email) vrátí true. meal uchovává typ jídla, který uživatel vybral z radio skupin.
  4. Jakmile máte hodnotu meal, vytvoříte SurveyListItem.CustomerSurvey, který obsahuje všechny informace o průzkumu. Vytáhne hodnoty pro questionOneAnswer, questionTwoAnswer a questionThreeAnswer z toggleButtonListeners(), který má pro tento účel posluchače.
  5. Zde uložíte customerSurvey voláním insertCustomerSurvey(customerSurvey) v CustomerSurveyViewModel, který zpracovává logiku uložení do Room.
  6. Přejdete na SurveyCompletedFragment.

Po přidání si všimnete, že customerSurveyViewModel a findNavController() mají červené podtržení. Chcete-li to napravit, přidejte nejprve inicializaci CustomerSurveyViewModel na začátek třídy, hned pod inicializaci questionThreeAnswer.

private val customerSurveyViewModel: CustomerSurveyViewModel by viewModels()

Ujistěte se, že jste přidali příslušné příkazy import, když vás k tomu IDE vyzve.

Sestavte a spusťte. Spusťte průzkum, zadejte požadovaný vstupní e-mail a vyberte odpovědi na otázky.

Obrázek průzkumu s odpověďmi

Skvělé, průzkum jste dokončili.

Zobrazení všech průzkumů pomocí zobrazení databáze Obrázek obrazovky

Klepněte na tlačítko VIEW SURVEYS… ups, zatím to nic nedělá. Nebojte se, brzy to napravíte.

V další části se naučíte vytvořit svůj první DatabaseView.

Vytvoření databázového pohledu

Pro vytvoření pohledu přidáte ke třídě nebo datové třídě anotaci @DatabaseView. Začněte tím, že přejdete do souboru customersurveys/SurveyListItem.kt. Jedná se o uzavřenou třídu s několika datovými třídami, které použijete v tomto tutoriálu.

Na konec třídy SurveyListItem, hned pod QuestionOneSadView, přidejte následující:

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

Tato datová třída přepisuje proměnnou email z třídy SurveyListItem a dědí od ní – to znamená, že je podtypem třídy SurveyListItem.

Po vytvoření této datové třídy přidejte @DatabaseView s dotazem SELECT pro získání všech e-mailových id z tabulky CustomerSurvey, kde je jídlo nastaveno na „Snídaně“, hned nad datovou třídu HappyBreakFastView. Vaše anotace by měla vypadat takto:

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

Několik věcí, které je třeba si uvědomit o dotazu uvnitř anotace:

  • Dotaz funguje jako jakýkoli jiný dotaz, který jste napsali v Room.
  • Při psaní dotazu je třeba vyžádat všechna pole, která máte ve své datové třídě. V tomto případě potřebujete pouze e-mail. Pro získání e-mailu z CustomerSurvey použijete SELECT CustomerSurvey.email From....
Poznámka: Pro tento návod ponecháte pohledy a entity uvnitř SurveyListItem, abyste se vyhnuli opakování a kód byl přehlednější. Pohledy nemusíte vždy podřazovat do uzavřené třídy, mohou být i ve vlastním samostatném souboru nebo třídě.

Gratulujeme, vytvořili jste svůj první pohled! Dále se podíváte, jak můžete pohled použít v dotazech DAO.

Použití pohledů na databázi místnosti v dotazech DAO

Nejprve do views v @Database aplikace zahrnete HappyBreakFastView.

Přejděte do database/AppDatabase.kt a uvnitř views přidejte SurveyListItem.HappyBreakFastView::class. Vaše aktualizovaná anotace @Database by měla vypadat následovně:

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

Všimněte si, že version = 2. Při každém přidání view v AppDatabase musíte aktualizovat verzi databáze – jinak vaše aplikace spadne. V tomto případě jste aktualizovali verzi na 2. Synchronizujte gradle, aby se všechny tyto změny uplatnily.

Dále přejděte do souboru customers/CustomerSurveysDao.kt a těsně pod getQuestionOneSadView() přidejte následující kód:

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

Tato metoda získá všechny zákazníky, kteří byli spokojeni s jakýmkoli aspektem průzkumu z restaurace. Abychom ji vysvětlili podrobněji:

  • Nejprve použijete HappyBreakFastView jako v běžném dotazu.
  • Voláním této metody v CustomerSurveyRepo získáte seznam všech zákazníků, kteří na některou z otázek odpověděli známkou Dobrý. Všimněte si, že návratovým typem metody je seznam LiveData typu SurveyListItem.HappyBreakFastView, což je držitel pozorovatelné proměnné.

Nyní jste vytvořili view a metodu pro dotaz na seznam zákazníků, kteří odpověděli kladně, v CustomerSurveysDao. V další části se dozvíte, jak tuto metodu volat z třídy úložiště.

Vyhledávání dat pomocí databázového pohledu

Přejděte do customersurveys/CustomerSurveyRepo.kt a přidejte následující metodu hned pod getQuestionOneSadView():

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

Tato metoda volá getHappyBreakFastCustomers() z CustomerSurveysDao, aby získala data z Room. Jejím návratovým typem je LiveData, což volajícímu této metody umožňuje sledovat případné změny v datech.

Dále přidáte volání getHappyBreakFastCustomers() v CustomerSurveyViewModel. To je zodpovědné za zobrazení dat do zobrazení – což v tomto případě není DatabaseView, ale AllSurveysFragment.

Přejděte do customersurveys/CustomerSurveyViewModel.kt a přidejte následující kód:

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

Tato proměnná získá svou hodnotu voláním getHappyBreakFastCustomers() z CustomerSurveyRepo. Je zde by lazy{}, aby se data nenačetla okamžitě, ale až při prvním přístupu k proměnné.

Dále budete aktualizovat uživatelské rozhraní, aby mohlo zobrazit data.

Zobrazení dat do uživatelského rozhraní

Přejděte na allsurveys/AllSurveysFragment.kt a na konec třídy přidejte následující kód:

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}

Pro vysvětlení, co kód dělá:

  • Nejprve zavolá happyBreakfastCustomers a pozoruje jeho hodnotu.
  • Uvnitř lambdy observe je kontrola, zda je customerSurveyList null nebo ne. Pokud je seznam null, nastavíte hlášení TextView No surveys found! na visible a skryjete RecyclerView. Pokud to není null, nastavíte viditelnost TextView na hodnotu GONE a zobrazíte RecyclerView. Zavoláte také initView(customerSurveyList) s hodnotou customerSurveyList z CustomerSurveyViewModel.
  • initView(customerSurveySurveyList: List) inicializuje CustomerSurveysAdapter s customerSurveyList a nastaví adaptér pro RecyclerView na CustomerSurveysAdapter, který nyní zobrazí seznam průzkumů uživatelského rozhraní.

IDE vás vyzve k přidání importu SurveyListItem. Pokud to neudělá, přidejte tento import:

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

Teď, když jste zobrazili data do uživatelského rozhraní, zbývá už jen několik dalších kroků, než bude vše fungovat bezchybně.

Dále přidáte kód, který se stará o načítání dat z Room v závislosti na možnosti vybrané v rozevíracím seznamu v uživatelském rozhraní, tj. widgetu Spinner.

Vybírání dat pro různé pohledy

Přidejte následující kus kódu hned pod onCreate v souboru 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() } } }}

Výše uvedený kus kódu nastaví onItemSelectedListener na filterSpinner a přepíše dvě metody: onNothingSelected a onItemSelected. Nechcete nic dělat, když není nic vybráno, takže onNothingSelected zůstane prázdná. Chcete však reagovat na to, když je vybrána položka, takže musíte implementovat onItemSelected.

onItemSelected má výraz when, který volá různé metody v závislosti na vybrané možnosti v filterSpinner. Tyto metody jsou podobné metodám getHappyBreakfastCustomers(), ale načítají data pomocí jiného DatabaseView.

Ujistěte se, že jste přidali import, když vás k tomu IDE vyzve.

Nakonec přidejte volání spinnerListener() uvnitř onViewCreated, hned za setupSpinner(), jak je znázorněno níže:

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

Teď, když máte vše připraveno pro načítání průzkumů, je vaším dalším krokem přidání kódu pro přechod na AllSurveysFragment.

Navigace na všechny průzkumy

Toto je poslední krok, který potřebujete, abyste viděli pohledy v akci.

Navigujte na completedsurvey/SurveyCompletedFragment.kt a odkomentujte kód uvnitř btnViewSurveys. Váš konečný výsledek bude vypadat takto:

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

Tady jednoduše nastavíte posluchače kliknutí pro tlačítko VIEW SURVEYS a přejdete na AllSurveysFragment.

Po odkomentování kódu vás prostředí IDE vyzve k importu findNavController(). Jednoduše importujte požadované.

Sestavte, spusťte a spusťte průzkum, poté odpovězte na otázky a odešlete je. Nakonec zobrazte Všechny průzkumy, kde budete moci načíst všechna data v závislosti na zvolené možnosti na spinneru.

Možnosti spinneru v aplikaci
Seznam průměrně spokojených zákazníků pomocí zobrazení databáze
Smutné večeře zákazníci nenalezeni pomocí zobrazení databáze

Gratulujeme! Dokončili jste svou zkušenost v restauraci The View. Doufáme, že jste se skvěle najedli, viděli úžasné výhledy a měli možnost naučit se, co jsou DatabaseViews.

Kam dál?

Stáhněte si závěrečný projekt pomocí tlačítka Stáhnout materiály v horní nebo dolní části výukového kurzu.

Další informace o funkcích Roomu najdete v oficiální dokumentaci systému Android.

Doufáme, že se vám tento výukový kurz Database Views Room líbil. Pokud máte nějaké dotazy, připomínky nebo úžasné úpravy této projektové aplikace, zapojte se do diskuse ve fóru níže.

raywenderlich.com Weekly

Zpravodaj raywenderlich.com je nejjednodušší způsob, jak zůstat v obraze o všem, co jako mobilní vývojář potřebujete vědět.

Získejte týdenní přehled našich výukových materiálů a kurzů a jako bonus získejte zdarma podrobný e-mailový kurz!

Průměrné hodnocení

4.8/5

Přidejte hodnocení tohoto obsahu

Pro přidání hodnocení se přihlaste

10 hodnocení

.

Leave a Reply