Utiliser Hive en Flutter

Dans cet article, je vais essayer de vous en dire le plus possible sur le package hive que j’utilise souvent dans mes projets. Je vous souhaite une lecture de code agréable.

Qu’est-ce que Hive ?

Hive est essentiellement une base de données locale NoSQL. Elle est très rapide en termes de performance, stocke les données avec une méthode de cryptage spéciale, ne contient pas de dépendances locales puisqu’elle est écrite en langage dart et la possibilité de stocker des modèles personnalisés sont les principales raisons de sa préférence. Si la base de données de votre projet est adaptée à l’utilisation de clés-valeurs, hive peut être une solution de base de données locale très appropriée.

Structure de travail

Hive est une solution de base de données locale qui fonctionne avec une structure en boîte. Par conséquent, lorsque nous l’utilisons, nous devons d’abord l’initialiser et ensuite ouvrir les boîtes que nous voulons utiliser. Ensuite, nous pouvons ajouter, mettre à jour ou supprimer nos données dans les boîtes que nous personnalisons avec des noms.

L’installation

Tout d’abord, nous incluons les plugins hive_flutter, build_runner et hive_generator nécessaires au projet dans le fichier pub.dev à pubspec.yaml.

dependencies:
  ...
  hive_flutter: ^1.1.0

dev_dependencies:
  ...
  build_runner: ^2.2.1
  hive_generator: ^1.1.3

Comme Hive est écrit en langage Dart, nous n’avons pas besoin de faire quoi que ce soit de spécial du côté d’Android et d’iOS après avoir ajouté les plugins au fichier pubspec.yaml. De cette manière, nous pouvons rapidement passer à la partie codage.

Fonctions de base

Hive dispose d’un ensemble de fonctions très simples. Nous pouvons facilement effectuer la plupart des opérations avec ces ensembles de fonctions. Résumons brièvement :

1- Avec la fonction Hive.initFlutter(), nous définissons et installons le plugin Hive dans notre projet avant de l’utiliser (il conviendrait de le définir avant la fonction runApp dans le fichier main.dart).

2- Avec la fonction Hive.openBox(boxName), nous ouvrons les boîtes que nous avons spécialement nommées.

3- Avec la fonction Hive.box(boxName), nous créons un objet pour la boîte que nous voulons utiliser.

4- Avec la fonction _box.add(value), nous ajoutons des données dans la boîte de manière séquentielle.

5- Avec la fonction _box.put(key, value), nous ajoutons des données à la clé spéciale que nous définirons dans la fonction (s’il y a une donnée, nous la mettons à jour).

6- Avec la fonction _box.get(key), nous obtenons les données dans la clé privée que nous définirons dans la fonction.

7- Avec la fonction _box.delete(key), nous supprimons les données dans la clé spéciale que nous définirons dans la fonction.

8- Avec la fonction _box.clear(), nous supprimons toutes les données à l’intérieur de la boîte.

9- Nous fermons la boîte avec la fonction _box.close().

//initialize hive
await Hive.initFlutter();

//open a box
Future<void> boxInit() async {
  await Hive.openBox(boxName);
}

//get box
Box getBox(){
  Box _box = Hive.box(boxName);
  return _box;
}

//add item to box with auto-incremented key
Future<void> addItemWithAutoIncrementKey(T item) async {
  await _box.add(item);
}

//add item to box with custom key
Future<void> addItemWithCustomKey(dynamic key, T item) async {
  await _box.put(key, item);
}

//get item from box
T? getItem(dynamic key) {
  return _box.get(key);
}

//remove item from box
Future<void> removeItem(dynamic key) async {
  await _box.delete(key);
}

//clear box
Future<void> clearBox() async {
  await _box.clear();
}

//close box
Future<void> closeBox() async {
  await _box.close();
}

Grâce aux fonctions données ci-dessus, nous pouvons sauvegarder des types de données tels que String, int, bool, qui sont les types de données de base du langage Dart sans aucune opération spéciale. Cependant, lorsque nous voulons sauvegarder un modèle spécial, nous devons effectuer quelques opérations supplémentaires.

Sauvegarde d’un modèle personnalisé

Si nous voulons sauvegarder un modèle personnalisé dans notre base de données locale, nous devons ajouter @HiveType(typeId : …) au début du modèle personnalisé que nous avons créé. Dans le champ laissé vide, nous devons donner une valeur entière indépendante (Cette valeur ne doit pas avoir la même valeur qu’un autre modèle personnalisé). Ensuite, pour chaque valeur du modèle que nous enregistrerons dans la base de données, nous devons ajouter @HiveField(…) au début de la valeur entre parenthèses, en commençant par zéro et en la numérotant de manière séquentielle. Enfin, nous devons ajouter la partie de code “nom_du_modèle.g.dart”; au début de notre fichier de modèle.

import 'package:hive_flutter/adapters.dart';
part 'todo_model.g.dart';

@HiveType(typeId: 1)
class Todo {
  @HiveField(0)
  int? userId;
  @HiveField(1)
  int? id;
  @HiveField(2)
  String? title;
  @HiveField(3)
  bool? completed;

  Todo({this.userId, this.id, this.title, this.completed});

  Todo.fromJson(Map<String, dynamic> json) {...}
  Map<String, dynamic> toJson() {...}
}

Grâce à ces modifications, nous avons converti notre modèle dans un format adapté à hive. Après avoir converti notre modèle au format approprié, nous exécuterons le code ci-dessous pour permettre aux plugins hive_generator et build_runner de créer l’extrait de code nécessaire pour enregistrer le modèle dans la base de données.

flutter pub run build_runner build

Après la création du fichier model_name.g.dart, nous devons ajouter la fonction Hive.registerAdapter(…) à notre structure de code pour informer le plugin Hive que le modèle que nous allons sauvegarder est un modèle personnalisé et qu’il contient des éléments personnalisés.

Future<void> openBox() async {
  Hive.registerAdapter(TodoAdapter());
  await Hive.openBox<T>(boxName);
}

Classe générique

Ce que nous avons fait jusqu’à présent était suffisant pour utiliser la puissance du plugin hive. Cependant, afin d’aller un peu plus loin et de nous améliorer, construisons une structure plus automatisée en utilisant la puissance des Generic Class et des enum et ayons la possibilité d’adapter ce système à toutes nos applications plus rapidement.

...

class BaseCacheManager<T> {
  Box<T>? _box;
  final CacheBoxNames boxName;

  BaseCacheManager(this.boxName);

  Future<void> openBox() async {
    registerAdaptor();
    if (!(_box?.isOpen ?? false)) {
      _box = await Hive.openBox<T>(boxName.name);
    }
  }

  registerAdaptor() {
    Hive.registerAdapter(TodoAdapter());
  }

  Future<void> updateItem(dynamic key, T val) async {
    await _box?.put(key, val);
  }

  T? getItem(dynamic key) {
    return _box?.get(key);
  }

  List<T>? getAllItems() {
    return _box?.values.toList();
  }

  saveAllItems(List<T>? items) {
    if (items != null) {
      _box?.addAll(items);
    }
  }
}
enum CacheBoxNames { auth, todo }

Dans le bloc de code ci-dessus, j’ai défini certaines des fonctions que j’ai utilisées comme exemples pour le repo que j’ai créé comme des fonctions dans la classe générique. J’ai également préféré créer des enums pour améliorer la lisibilité du code et automatiser le nommage. Je n’ai pas défini certaines fonctions (delete, clear) parce que je ne les utiliserais pas dans l’exemple d’application.

//créer une instance de gestionnaire de cache
final BaseCacheManager<Todo> _manager = BaseCacheManager<Todo>(CacheBoxNames.todo);

//utilisation de l'instance du gestionnaire de cache
List<Todo>? items = _manager.getAllItems();
_manager.saveAllItems(items);

Dans le bloc de code ci-dessus, j’ai créé un exemple d’utilisation de la structure générique que j’ai établie. Sur la base de cet exemple, vous pouvez définir et développer des fonctions en fonction de vos propres besoins dans le projet existant ou dans votre propre projet, et vous pouvez gérer librement votre processus par le biais des objets que vous créez.

Je vous remercie d’avoir pris votre temps précieux pour lire cet article. A bientôt dans le prochain article.💙

0 Shares:
Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

You May Also Like
Lire plus

Flutter 3.16

Flutter v3.16 est une version stable trimestrielle de Flutter qui apporte de nouvelles fonctionnalités passionnantes et des améliorations…
Lire plus

Flutter et SQLite

Dans cette histoire, je vais vous raconter mon expérience de l’implémentation d’une base de données hors ligne dans…
Lire plus

Prep4Dev

A mini application developed with Flutter and powered by Gemini API to help developers prepare effectively for their…