Lekce 13 - Diář s databází v Dartu
V minulé lekci, Kolekce Set, Queue a Map v Dartu, jsme si představili kolekce Dartu. V tomto tutoriálu si do kolekcí zkusíme uložit objekty.
Prvně jsem chtěl udělat databázi uživatelů, ale uživatele jsme tu již
několikrát měli. Jelikož jsme se nedávno naučili datum a čas,
naprogramujeme si diář. Do databáze budeme ukládat jednotlivé záznamy a
vždy vypíšeme ten dnešní a zítřejší. Databáze to nebude samozřejmě
ta v tom pravém slova smyslu (na to ještě nemáme zkušenosti), ale bude se
jednat právě o List
v operační paměti počítače. Bude
umožňovat záznamy přidávat, hledat je podle data a mazat podle data a
času.
Založte si nový projekt, který pojmenujeme diar
.
Záznam
Prvně si udělejme třídu, jejíž instance budeme ukládat. Nazvěme ji
Zaznam
. Záznam v diáři se bude vázat k nějakému datu a času.
Také bude obsahovat nějaký text. Např.:
12. ledna 2013 - Vyvenčit psa
. To je asi vše, třída může
vypadat takto:
class Zaznam { DateTime datumCas; String text; Zaznam(this.datumCas, this.text); @override String toString() { return '$datumCas $text'; } }
Třída v podstatě slouží jen k záznamu dat a nemá žádné metody (až
na konstruktor a toString()
).
Databáze
Protože program bude o něco složitější, rozdělíme jej do více
objektů (vrstev). Záznam máme, nyní si vytvoříme objekt
Databaze
, ve které budou záznamy uloženy. Bude mít privátní
seznam typu Zaznam
. Diář bude umožňovat záznamy přidávat,
mazat a vyhledávat podle data. K projektu tedy přidáme třídu
Databaze
:
class Databaze {
List<Zaznam> _zaznamy = [];
}
Třída tedy slouží pouze pro manipulaci s daty. Obsahuje vnitřní kolekci
_zaznamy
. Dodejme třídě metody pro přidání, vymazání a
vyhledání záznamu.
Přidání záznamu by mělo být jasné:
void pridejZaznam(DateTime datumCas, String text) { _zaznamy.add(new Zaznam(datumCas, text)); }
Jako druhou metodu přidejme nalezení záznamů v daný den. Metoda bude
vracet seznam nalezených záznamů, protože jich pro ten den může být v
databázi více. Záznamy budeme moci vyhledávat podle data i času nebo jen
podle data. Můžeme tak najít záznamy v konkrétní den bez ohledu na to, v
jakou jsou hodinu. Podle čeho budeme chtít vyhledávat bude udávat parametr
dleCasu
typu bool
. Pokud bude false
,
hledáme jen podle data bez ohledu na čas. Seznam si nejprve vytvoříme a
poté do něj přidáváme záznamy, které odpovídají hledanému datu.
Odpovídat musí buď celé datum a čas (pokud hledáme i podle času) nebo jen
část dnů, pokud hledáme jen podle data. Naplněný seznam s nalezenými
záznamy vrátíme.
List<Zaznam> najdiZaznamy(DateTime datum, bool dleCasu) { List<Zaznam> nalezene = []; _zaznamy.forEach((Zaznam zaznam) { if ((dleCasu && zaznam.datumCas.isAtSameMomentAs(datum)) || (!dleCasu && zaznam.datumCas.difference(datum).inDays == 0 && zaznam.datumCas.day == datum.day))) { nalezene.add(zaznam); } }); return nalezene; }
Nakonec přidáme vymazání záznamů v určitou dobu. To provedeme pomocí
metody najdiZaznamy()
a nalezené záznamy jednoduše proiterujeme
a ze seznamu odstraníme. Budeme mazat podle přesného data i času, 2.
parametr u metody najdiZaznamy()
bude tedy true
:
void vymazZaznamy(DateTime datum) {
List<Zaznam> nalezeno = najdiZaznamy(datum, true);
nalezeno.forEach((Zaznam zaznam) {
_zaznamy.remove(zaznam);
});
}
Diář
Nyní si přidáme k projektu poslední třídu, bude to samotný diář.
Nazvěme ji Diar
. Ten již bude obsahovat metody pro komunikaci s
uživatelem. Všimněte si, jak aplikaci rozdělujeme a jednotlivé její
části zapouzdřujeme. Seznam je zapouzdřen v databázi, která nad ním
postavila další metody pro bezpečnou manipulaci s jeho obsahem. Samotnou
databázi nyní vložíme do diáře. Tím oddělíme logiku a práci s daty od
komunikace s uživatelem a dalšími vstupy/výstupy programu. Třída
Diar
tedy bude komunikovat s uživatelem a data od něj předá
databázi.
class Diar { Databaze _databaze = new Databaze(); }
Jako další přidejme pomocnou metodu _zjistiDatumCas()
, která
vyzve uživatele k zadání data a času a vrátí instanci
DateTime
nastavenou na tuto hodnotu. Jediným bodem k
přemýšlení je zde validace vstupu od uživatele:
DateTime _zjistiDatumCas() { print('Zadejte datum a čas ve tvaru [2018-01-14 14:00]:'); DateTime datumCas; while (true) { try { datumCas = DateTime.parse(stdin.readLineSync(encoding: UTF8)); break; } catch (e) { print('Chybné zadání, zadejte znovu datum a čas:'); } } return datumCas; }
Přidejme metodu vypisZaznamy()
, která najde záznamy v daný
den a vypíše je:
void vypisZaznamy(DateTime den) {
List<Zaznam> zaznamy = _databaze.najdiZaznamy(den, false);
zaznamy.forEach((Zaznam zaznam) => print(zaznam));
}
Jelikož metoda forEach()
aplikuje funkci o jednom parametru,
kterou jí předáváme v parametru, lze kód zjednodušit a předávat pouze
funkci print()
:
void vypisZaznamy(DateTime den) {
List<Zaznam> zaznamy = _databaze.najdiZaznamy(den, false);
zaznamy.forEach(print);
}
Metoda pro vyzvání uživatele k vložení parametrů nového záznamu a jeho přidání do databáze bude následující:
void pridejZaznam() { DateTime datumCas = _zjistiDatumCas(); print('Zadejte text záznamu:'); String text = stdin.readLineSync(encoding: UTF8); _databaze.pridejZaznam(datumCas, text); }
Zbývá záznamy vyhledávat a mazat. Metoda k vyhledání vrátí seznam s nalezenými záznamy (jen podle data, přesný čas nebude hrát roli). Vyzveme uživatele k zadání data a to předáme databázi. Výsledek zobrazíme.
void vyhledejZaznamy() { // Zadání data uživatelem DateTime datumCas = _zjistiDatumCas(); // Vyhledání záznamů List<Zaznam> zaznamy = _databaze.najdiZaznamy(datumCas, false); // Výpis záznamů if (zaznamy.length > 0) { print('Nalezeny tyto záznamy:'); zaznamy.forEach(print); } else { // Nenalezeno print('Nebyly nalezeny žádné záznamy.'); } }
Mazání záznamů je triviální:
void vymazZaznamy() { print('Budou vymazány záznamy v daný den a hodinu'); DateTime datumCas = _zjistiDatumCas(); _databaze.vymazZaznamy(datumCas); }
Jako poslední přidejme metodu pro vypsání úvodní obrazovky programu s aktuálním datem a časem a událostmi na dnešek a zítřek.
void vypisUvodniObrazovku() { print(''' Vítejte v diáři! Dnes je ${new DateTime.now()} Dnes: ------'''); vypisZaznamy(new DateTime.now()); print(''' Zítra: ------'''); vypisZaznamy(new DateTime.now().add(new Duration(days: 1))); print(''); }
Můžeme vítězoslavně přejít do main.dart
a vytvořit
instanci diáře. Zde umístíme také hlavní cyklus programu s menu programu a
reakcí na volbu uživatele. Je to ta nejvyšší vrstva programu:
void main() { // instance diáře Diar diar = new Diar(); String volba = '0'; // hlavní cyklus while (volba != '4') { diar.vypisUvodniObrazovku(); print(''' Vyberte si akci: 1 - Přidat záznam 2 - Vyhledat záznamy 3 - Vymazat záznam 4 - Konec '''); volba = stdin.readLineSync(encoding: UTF8).trim().split('').first; // reakce na volbu switch (volba) { case '1': diar.pridejZaznam(); break; case '2': diar.vyhledejZaznamy(); break; case '3': diar.vymazZaznamy(); break; case '4': break; default: print('Neplatná volba, stiskněte libovolnou klávesu a opakujte volbu.'); break; } } }
Kód výše není složitý a již jsme tu podobný měli mockrát. Výsledek naší aplikace:
Konzolová aplikace
Vítejte v diáři!
Dnes je 2018-01-12 23:48:06.541360
Dnes:
------
2018-01-12 00:00:00.000 Učit se programovat
2018-01-12 19:30:00.000 Posilovna!
Zítra:
------
2018-01-13 07:35:00.000 Jít ven běhat! (Alespoň 30 min)
Vyberte si akci:
1 - Přidat záznam
2 - Vyhledat záznamy
3 - Vymazat záznam
4 - Konec
Tímto jsme si práci s kolekcemi, konkrétně se seznamem, osvojili ještě
lépe a bude nám to poměrně dlouho stačit. Na závěr bych dodal, že takto
si můžete udělat databázi čehokoli. Můžete ukládat články, úlohy,
slony, cokoli, co chcete v databázi spravovat. A co dál? V příští lekci,
, to bude o rozhraní a mixinech. V OOP nás toho čeká ještě dost.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 4x (3.62 kB)
Aplikace je včetně zdrojových kódů v jazyce Dart