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
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.
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.
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 View
s iEntity
s 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 DatabaseView
s a Entity
s:
- S
Entity
s můžete použít INSERT, UPDATE a DELETE, ale ne sDatabaseView
. - 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:
- Získáte e-mail z
editEmail
a přiřadíte jej do proměnné:email
. - Tato kontrola podmínky volá
validateEmail(email)
, který kontroluje, zda je e-mailnull
nebo ne. Pokud jenull
, vrátífalse
. Také kontroluje, zda je zadaný e-mail platný, a pokud není, vrátífalse
. - 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. - Jakmile máte hodnotu
meal
, vytvoříteSurveyListItem.CustomerSurvey
, který obsahuje všechny informace o průzkumu. Vytáhne hodnoty proquestionOneAnswer
,questionTwoAnswer
aquestionThreeAnswer
ztoggleButtonListeners()
, který má pro tento účel posluchače. - Zde uložíte
customerSurvey
voláníminsertCustomerSurvey(customerSurvey)
vCustomerSurveyViewModel
, který zpracovává logiku uložení do Room. - 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.
Skvělé, průzkum jste dokončili.
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žijeteSELECT CustomerSurvey.email From...
.
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 seznamLiveData
typuSurveyListItem.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 seznamnull
, nastavíte hlášeníTextView
No surveys found! na visible a skryjeteRecyclerView
. Pokud to nenínull
, nastavíte viditelnostTextView
na hodnotu GONE a zobrazíteRecyclerView
. Zavoláte takéinitView(customerSurveyList)
s hodnotoucustomerSurveyList
zCustomerSurveyViewModel
. -
initView(customerSurveySurveyList: List)
inicializujeCustomerSurveysAdapter
scustomerSurveyList
a nastaví adaptér proRecyclerView
naCustomerSurveysAdapter
, 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.
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
.
Leave a Reply