Flutter: Ukládání dat

Z MiS
(Rozdíly mezi verzemi)
Přejít na: navigace, hledání
(Lokální export do JSON pomocí jsonEncode/Decode().)
(Vytvořená sekce o Firebase – zatím pomocí ChatGPT.)
Řádka 163: Řádka 163:
 
* [https://docs.flutter.dev/data-and-backend/serialization/json Flutter Docs > JSON and serialization]
 
* [https://docs.flutter.dev/data-and-backend/serialization/json Flutter Docs > JSON and serialization]
 
* [https://docs.flutter.dev/cookbook/persistence/reading-writing-files Flutter Docs > Read and write files]
 
* [https://docs.flutter.dev/cookbook/persistence/reading-writing-files Flutter Docs > Read and write files]
 +
  
  
 
== Lokální databáze: Hive ==
 
== Lokální databáze: Hive ==
 +
 +
* Data ukládá binárně, ale stále na lokální zařízení.
  
 
=== Zdroje ===
 
=== Zdroje ===
 
* [https://medium.com/@ChanakaDev/hive-vs-shared-preferences-10353068a8a6 Medium.com: ChanakaDev > Hive vs. Shared Preferences]
 
* [https://medium.com/@ChanakaDev/hive-vs-shared-preferences-10353068a8a6 Medium.com: ChanakaDev > Hive vs. Shared Preferences]
 +
 +
  
 
== Google Firestore ==
 
== Google Firestore ==
 +
 +
* Google Firestore je cloudová NoSQL databáze od Google, která je součástí platformy Firebase.
 +
 +
; Vlastnosti
 +
* Firebase je dobře integrovaná do frameworku Flutter (Flutter také vyvíjí Google)
 +
* Data se ukládají do cloudu – data může sdílet mobilní i webová aplikace
 +
* Synchronizace dat v reálném čase
 +
* Pro malé projekty stačí varianta zdarma (pro větší bude třeba platit)
 +
 +
=== Struktura dat ve Firestore ===
 +
* Data se neukládají do entit jako u ER databází – spíše jako několik seznamů objektů.
 +
 +
; Pojmy:
 +
* Dokument (Document) ... konkrétní záznam (jako jeden řádek v databázi) – například údaje o jednom uživateli.
 +
* Pole (Field) ... konkrétní hodnota (atribut) – například jméno uživatele
 +
* Kolekce (Collection) ... odpovídá entitě v ER databázích – je to vlastně seznam dokumentů
 +
* Databáze (Database) ... skupina souvisejících kolekcí
 +
* Projekt (Project) ... jeden projekt obvykle odpovídá jednomu projektu ve Flutteru (jedné aplikaci, která může mít více podob – Android, IOS, web, ...)
 +
 +
Příklad:
 +
users (kolekce)
 +
    └── user1 (dokument)
 +
          ├── name: "Jan"
 +
          ├── age: 18
 +
          └── email: "jan@email.cz"
 +
 +
=== Vytvoření projektu ve Firebase===
 +
 +
#Jdi na: [https://console.firebase.google.com Console.firebase.google.com]
 +
#Klikni na Vytvořit projekt
 +
#Zadej název projektu
 +
#Po vytvoření přidej aplikaci (Android / iOS / Web)
 +
 +
===Propojení Flutter aplikace s Firebase===
 +
 +
Ve Flutter projektu spusť:
 +
 +
flutter pub add firebase_core
 +
flutter pub add cloud_firestore
 +
 +
Poté inicializuj Firebase v main.dart:
 +
 +
import 'package:firebase_core/firebase_core.dart';
 +
import 'package:flutter/material.dart';
 +
 +
void main() async {
 +
  WidgetsFlutterBinding.ensureInitialized();
 +
  await Firebase.initializeApp();
 +
  runApp(MyApp());
 +
}
 +
 +
=== Ukládání dat do Firestore===
 +
 +
; Importuj Firestore:
 +
 +
import 'package:cloud_firestore/cloud_firestore.dart';
 +
 +
; Vytvoření instance pro přístup k databázi:
 +
 +
final FirebaseFirestore db = FirebaseFirestore.instance;
 +
 +
; Přidání nového dokumentu
 +
await db.collection('users').add({
 +
  'name': 'Jan',
 +
  'age': 18,
 +
  'email': 'jan@email.cz',
 +
});
 +
 +
Tím se:
 +
# vytvoří kolekce users (pokud neexistuje)
 +
# přidá nový dokument s automatickým ID
 +
 +
; Uložení dokumentu s vlastním ID
 +
await db.collection('users').doc('student1').set({
 +
  'name': 'Petra',
 +
  'age': 17,
 +
});
 +
 +
=== Čtení dat z Firestore jednorázově===
 +
 +
var snapshot = await db.collection('users').get();
 +
 +
for (var doc in snapshot.docs) {
 +
  print(doc.data());
 +
}
 +
 +
===Načtení v reálném čase ===
 +
 +
Firestore umožňuje poslouchat změny. Data se pak automaticky aktualizují, pokud proběhne změna v databázi (například z jiného zařízení připojeného ke stejnému projektu):
 +
 +
StreamBuilder(
 +
  stream: db.collection('users').snapshots(),
 +
  builder: (context, snapshot) {
 +
    if (!snapshot.hasData) {
 +
      return CircularProgressIndicator();
 +
    }
 +
 +
    var docs = snapshot.data!.docs;
 +
 +
    return ListView(
 +
      children: docs.map((doc) {
 +
        return ListTile(
 +
          title: Text(doc['name']),
 +
        );
 +
      }).toList(),
 +
    );
 +
  },
 +
);
 +
 +
=== Aktualizace dat===
 +
await db.collection('users').doc('student1').update({
 +
  'age': 18,
 +
});
 +
 +
=== Smazání dat===
 +
 +
; Smazání dokumentu
 +
await db.collection('users').doc('student1').delete();
 +
 +
=== Bezpečnostní pravidla (Rules) ===
 +
 +
Ve Firebase konzoli nastav pravidla přístupu.
 +
 +
Například pouze pro přihlášené uživatele:
 +
 +
rules_version = '2';
 +
service cloud.firestore {
 +
  match /databases/{database}/documents {
 +
    match /{document=**} {
 +
      allow read, write: if request.auth != null;
 +
    }
 +
  }
 +
}
 +
 +
=== Zdroje ===
 +
* Sekce o Firebase byla vytvořena pomocí služby [https://www.chatgpt.com ChatGPT].
 +
* [https://cloud.google.com/firestore/pricing Google Cloud > Firestore Pricing]
 +
 +
  
 
== Vlastní backend: ServerPod ==
 
== Vlastní backend: ServerPod ==
 +
 +
* Framework, který umožňuje vytvořit projekt Flutteru se dvěma částmi: backendem a frontendem.
 +
* Backend je následně možné spustit na svém serveru.
 +
* Frontend běží na desktopu.

Verze z 22. 2. 2026, 01:55


Pro trvalé uložení dat i po vypnutí aplikace můžeme data uložit:

Následuje několik příkladů možných řešení.

Obsah

Lokální export: jsonEncode/jsonDecode

Vlastnosti

Postup zápisu

  1. Nalezení umístění souboru:
    • Využij balíček path_provider a metodu getApplicationDocumentsDirectory().
    • Pro zápis do souboru použij třídu File a metodu writeAsString.
  2. Převod dat na JSON
    • Využij balíček dart:convert.
    • Pro parsování JSON využij metodu jsonDecode(list) – výsledkem bude textová reprezentace objektu ve formátu JSON.

Postup čtení

  1. Nalezení umístění souboru:
    • Využij balíček path_provider a metodu getApplicationDocumentsDirectory().
    • Pro čtení souboru použij třídu File a metodu readAsString.
  2. Převod dat na JSON
    • Využij balíček dart:convert.
    • Pro ukládání využij metodu jsonEncode(list) – výsledkem bude textová reprezentace objektu ve formátu JSON.

Ukázka použití v aplikaci

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:convert';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Úložiště Demo',
      home: HomePage(storage: FileStorage()),
    );
  }
}

class Zaznam {
  final String jmeno;
  final int pocet;

  const Zaznam({ required this.jmeno, required this.pocet, }); 

  // Převod do JSON
  Map<String, dynamic> toJson() => {
    'jmeno': jmeno,
    'pocet': pocet,
  };

  // Obnov z JSON
  factory Zaznam.fromJson(Map<String, dynamic> json) {
    return Zaznam(
      jmeno: (json['jmeno']),
      pocet: json['pocet'] as int,
    );
  }
}

/// Práce se soubory
class FileStorage {
  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();
    return directory.path;
  }

  Future<File> get _localFile async {
    final path = await _localPath;
    return File('$path/data.txt');
  }

  Future<String> readFile() async {
    final file = await _localFile;
    return file.readAsString();
  }

  Future<void> writeFile(String content) async {
    final file = await _localFile;
    await file.writeAsString(content);
  }
}

/// Stav aplikace včetně zápisu do souboru
class HomePage extends StatefulWidget {
  final FileStorage storage;
  const HomePage({required this.storage});
  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List<Zaznam> _seznam = [];

  @override
  void initState() {
    super.initState();
    _loadData();   // Načtení dat při startu
  }

  Future<void> _loadData() async {
    try {
      final jsonString = await widget.storage.readFile();
      final List<dynamic> decoded = jsonDecode(jsonString);
      setState(() {
        _seznam = decoded
            .map((item) => Zaznam.fromJson(item as Map<String, dynamic>))
            .toList();
      });
    } catch (e) {
      TODO: Zobraz chybové hlášení vhodným způsobem.
    }
  }

  Future<void> _saveData() async {
    final jsonString = jsonEncode(
      _seznam.map((z) => z.toJson()).toList()
    );
    await widget.storage.writeFile(jsonString);
  }

  void _addRecord() {
    setState(() {
      _seznam.add(Zaznam(
        jmeno: 'Josef',
        pocet: 1000,
      ));
    });
    _saveData();
  } 

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // ... vytvoř GUI
    );
  }
}

Tip

 Zdroje


Lokální databáze: Hive

Zdroje


Google Firestore

Vlastnosti

Struktura dat ve Firestore

Pojmy

Příklad:

users (kolekce)
   └── user1 (dokument)
         ├── name: "Jan"
         ├── age: 18
         └── email: "jan@email.cz"

Vytvoření projektu ve Firebase

  1. Jdi na: Console.firebase.google.com
  2. Klikni na Vytvořit projekt
  3. Zadej název projektu
  4. Po vytvoření přidej aplikaci (Android / iOS / Web)

Propojení Flutter aplikace s Firebase

Ve Flutter projektu spusť:

flutter pub add firebase_core
flutter pub add cloud_firestore

Poté inicializuj Firebase v main.dart:

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

Ukládání dat do Firestore

Importuj Firestore
import 'package:cloud_firestore/cloud_firestore.dart';
Vytvoření instance pro přístup k databázi
final FirebaseFirestore db = FirebaseFirestore.instance;
Přidání nového dokumentu
await db.collection('users').add({
  'name': 'Jan',
  'age': 18,
  'email': 'jan@email.cz',
});

Tím se:

  1. vytvoří kolekce users (pokud neexistuje)
  2. přidá nový dokument s automatickým ID
Uložení dokumentu s vlastním ID
await db.collection('users').doc('student1').set({
  'name': 'Petra',
  'age': 17,
});

Čtení dat z Firestore jednorázově

var snapshot = await db.collection('users').get();

for (var doc in snapshot.docs) {
  print(doc.data());
}

Načtení v reálném čase

Firestore umožňuje poslouchat změny. Data se pak automaticky aktualizují, pokud proběhne změna v databázi (například z jiného zařízení připojeného ke stejnému projektu):

StreamBuilder(
  stream: db.collection('users').snapshots(),
  builder: (context, snapshot) {
    if (!snapshot.hasData) {
      return CircularProgressIndicator();
    }

    var docs = snapshot.data!.docs;

    return ListView(
      children: docs.map((doc) {
        return ListTile(
          title: Text(doc['name']),
        );
      }).toList(),
    );
  },
);

Aktualizace dat

await db.collection('users').doc('student1').update({
  'age': 18,
});

Smazání dat

Smazání dokumentu

await db.collection('users').doc('student1').delete();

Bezpečnostní pravidla (Rules)

Ve Firebase konzoli nastav pravidla přístupu.

Například pouze pro přihlášené uživatele:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Zdroje


Vlastní backend: ServerPod

Osobní nástroje
Jmenné prostory
Varianty
Akce
Výuka
Navigace
Nástroje