Flutter: Ukládání dat

Z MiS
(Rozdíly mezi verzemi)
Přejít na: navigace, hledání
m (Vytvoření kostry stránky)
 
(Lokální export do JSON pomocí jsonEncode/Decode().)
Řádka 1: Řádka 1:
 
[[Category:VSE]][[Category:Informatika]][[Category:Programování]][[Category:Flutter]]
 
[[Category:VSE]][[Category:Informatika]][[Category:Programování]][[Category:Flutter]]
  
== Ukládání dat lokálně: JSON ==
+
Pro trvalé uložení dat i po vypnutí aplikace můžeme data uložit:
 +
* na lokální disk konkrétního zařízení
 +
* do síťového úložiště (databáze, cloudové úložiště)
 +
* můžeme rozdělit aplikaci na frontend a backend, kde data budou uložena v backendu (opět obvykle v databázi).
 +
 
 +
Následuje několik příkladů možných řešení.
 +
 
 +
== Lokální export: jsonEncode/jsonDecode ==
 +
 
 +
=== Vlastnosti ===
 +
* Formát JSON lze zpracovávat i v dalších aplikacích – je vhodný pro výměnu dat mezi aplikacemi a je textový.
 +
* Jednoduše lze uložit seznam objektů. Složitější vnořované struktury objektů je třeba ručně převádět.
 +
* Není vhodné pro větší objem dat – převod na text může zvětšit objem dat.
 +
* Vhodné zejména pro textová data: texty, celá čísla, logické hodnoty. Méně vhodné pro desetinná čísla, obrázky, ... z důvodu nutné konverze na text.
 +
* Formát JSON neukládá datové typy.
 +
* Výsledek je uložen lokálně – převod z mobilní aplikace na desktop apod. je třeba řešit ručně.
 +
 
 +
=== Postup zápisu ===
 +
# Nalezení umístění souboru:
 +
#* Využij balíček <code>path_provider</code> a metodu <code>getApplicationDocumentsDirectory()</code>.
 +
#* Pro zápis do souboru použij třídu <code>File</code> a metodu <code>writeAsString</code>.
 +
# Převod dat na JSON
 +
#* Využij balíček <code>dart:convert</code>.
 +
#* Pro parsování JSON využij metodu <code>jsonDecode(list)</code> – výsledkem bude textová reprezentace objektu ve formátu JSON.
 +
 
 +
=== Postup čtení ===
 +
# Nalezení umístění souboru:
 +
#* Využij balíček <code>path_provider</code> a metodu <code>getApplicationDocumentsDirectory()</code>.
 +
#* Pro čtení souboru použij třídu <code>File</code> a metodu <code>readAsString</code>.
 +
# Převod dat na JSON
 +
#* Využij balíček <code>dart:convert</code>.
 +
#* Pro ukládání využij metodu <code>jsonEncode(list)</code> – 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 ===
 +
* Pro větší objemy dat či komplexnější data lze pro export do formátu JSON využít balíček <code>json_serializable</code>.
 +
 
 +
=== Zdroje ===
 +
* [https://hatchjs.com/list-to-json-flutter/ HatchJS.com > How to Convert a List to JSON in Flutter]
 +
* [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]
 +
 
 +
 
 +
== Lokální databáze: Hive ==
 +
 
 +
=== Zdroje ===
 +
* [https://medium.com/@ChanakaDev/hive-vs-shared-preferences-10353068a8a6 Medium.com: ChanakaDev > Hive vs. Shared Preferences]
 +
 
 +
== Google Firestore ==
 +
 
 +
== Vlastní backend: ServerPod ==

Verze z 22. 2. 2026, 01:04


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

Vlastní backend: ServerPod

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