IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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

 

Předchozí článek
Kolekce Set, Queue a Map v Dartu
Všechny články v sekci
Objektově orientované programování v Dartu
Článek pro vás napsal Honza Bittner
Avatar
Uživatelské hodnocení:
2 hlasů
FIT ČVUT alumnus :-) Sleduj mě na https://twitter.com/tenhobi a ptej se na cokoli na https://github.com/tenhobi/ama.
Aktivity