Using NoSQL Databases like Hive and Isar in Flutter

Flutter is a versatile framework for building cross-platform applications. While traditional relational databases are widely used, NoSQL databases offer compelling alternatives, especially when dealing with unstructured or semi-structured data, scalability requirements, and real-time data synchronization needs. This blog post will explore how to leverage NoSQL databases like Hive and Isar within your Flutter applications.

What are NoSQL Databases?

NoSQL databases are non-relational databases that provide a mechanism for storage and retrieval of data that is modeled in means other than the tabular relations used in relational databases. Common types include document stores, key-value stores, graph databases, and column-family stores.

Why Use NoSQL in Flutter?

  • Flexibility: Handle various data types and structures.
  • Scalability: Easily scale horizontally to accommodate large amounts of data and high traffic.
  • Performance: Optimized for speed with specific data models.
  • Offline Support: Well-suited for apps requiring offline capabilities and data synchronization.

Hive: Lightweight Key-Value Database for Flutter

Hive is a lightweight and fast key-value database written in pure Dart. It is perfect for Flutter apps that need a simple, fast, and reliable local storage solution.

Key Features of Hive

  • Pure Dart: Works on all platforms supported by Flutter.
  • Cross-Platform: Suitable for mobile, desktop, and web.
  • Encryption: Supports encryption to protect sensitive data.
  • No Native Dependencies: Easy to integrate and use.

How to Implement Hive in Flutter

Step 1: Add Dependencies

Include the hive and hive_flutter packages in your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  hive: ^2.2.3
  hive_flutter: ^1.1.0

dev_dependencies:
  hive_generator: ^2.0.1
  build_runner: ^2.1.7

Run flutter pub get to install the packages.

Step 2: Initialize Hive

Initialize Hive in your main function:

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Hive.initFlutter();
  runApp(MyApp());
}
Step 3: Define a Hive Object (Optional)

For complex data, define a Hive object with an adapter. First, annotate your class:

import 'package:hive/hive.dart';

part 'person.g.dart';

@HiveType(typeId: 0)
class Person {
  @HiveField(0)
  String name;

  @HiveField(1)
  int age;

  Person({required this.name, required this.age});
}

Run the generator to create the adapter:

flutter pub run build_runner build
Step 4: Open a Box

Open a Hive box to store and retrieve data:

import 'package:hive_flutter/hive_flutter.dart';

class HiveService {
  static const String personBoxName = 'personBox';

  static Future openBoxes() async {
    await Hive.openBox(personBoxName);
  }

  static Box getPersonBox() => Hive.box(personBoxName);

  static Future closeBoxes() async {
    await Hive.close();
  }
}
Step 5: Perform CRUD Operations

Use the box to perform CRUD operations:

import 'package:hive/hive.dart';

class PersonCRUD {
  static void addPerson(Person person) {
    final box = HiveService.getPersonBox();
    box.add(person);
  }

  static List getAllPersons() {
    final box = HiveService.getPersonBox();
    return box.values.toList();
  }

  static void updatePerson(int index, Person updatedPerson) {
    final box = HiveService.getPersonBox();
    box.putAt(index, updatedPerson);
  }

  static void deletePerson(int index) {
    final box = HiveService.getPersonBox();
    box.deleteAt(index);
  }
}

Isar: Multi-Platform, Ultralight Database for Flutter

Isar is another powerful NoSQL database designed for Flutter, offering excellent performance and ease of use.

Key Features of Isar

  • Multi-Platform: Works on mobile, desktop, and web.
  • High Performance: Optimized for fast reads and writes.
  • Strongly Typed: Reduces runtime errors.
  • Supports Relations: Can establish relationships between objects.

How to Implement Isar in Flutter

Step 1: Add Dependencies

Include the isar and isar_flutter_libs packages in your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  isar: ^3.1.0+1
  isar_flutter_libs: ^3.1.0+1

dev_dependencies:
  isar_generator: ^3.1.0+1
  build_runner: ^2.1.7

Run flutter pub get to install the packages.

Step 2: Define an Isar Collection

Create a class and annotate it to be an Isar collection:

import 'package:isar/isar.dart';

part 'student.g.dart';

@collection
class Student {
  Id? id;

  @Index()
  String? name;

  int? age;
}
Step 3: Generate Isar Code

Run the generator to create the Isar code:

flutter pub run build_runner build
Step 4: Initialize Isar

Initialize Isar in your main function:

import 'package:flutter/material.dart';
import 'package:isar/isar.dart';
import 'package:path_provider/path_provider.dart';

import 'student.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final dir = await getApplicationDocumentsDirectory();
  final isar = await Isar.open(
    [StudentSchema],
    directory: dir.path,
  );

  runApp(MyApp(isar: isar));
}

class MyApp extends StatelessWidget {
  final Isar isar;

  const MyApp({Key? key, required this.isar}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Isar Demo',
      home: MyHomePage(isar: isar),
    );
  }
}
Step 5: Perform CRUD Operations

Use Isar to perform CRUD operations:

import 'package:flutter/material.dart';
import 'package:isar/isar.dart';
import 'student.dart';

class IsarService {
  static Future addStudent(Isar isar, String name, int age) async {
    final newStudent = Student()
      ..name = name
      ..age = age;

    await isar.writeTxn(() async {
      await isar.students.put(newStudent);
    });
  }

  static Future<List> getAllStudents(Isar isar) async {
    return await isar.students.where().findAll();
  }

  static Future updateStudent(Isar isar, int id, String newName, int newAge) async {
    await isar.writeTxn(() async {
      final student = await isar.students.get(id);
      if (student != null) {
        student.name = newName;
        student.age = newAge;
        await isar.students.put(student);
      }
    });
  }

  static Future deleteStudent(Isar isar, int id) async {
    await isar.writeTxn(() async {
      await isar.students.delete(id);
    });
  }
}

Real-World Use Cases

  • Offline Caching: Storing data locally for offline access using Hive or Isar.
  • User Preferences: Storing user settings and configurations using key-value pairs in Hive.
  • Data-Intensive Apps: Handling large datasets efficiently with Isar’s optimized storage.
  • Real-Time Synchronization: Combining NoSQL databases with cloud solutions like Firebase for real-time data synchronization.

Conclusion

NoSQL databases such as Hive and Isar offer compelling options for Flutter developers seeking flexible, scalable, and performant data storage solutions. Hive’s simplicity and Dart purity make it an excellent choice for lightweight applications, while Isar’s performance and multi-platform support cater to more demanding requirements. By integrating these databases into your Flutter projects, you can create robust applications capable of handling a wide array of data management tasks.