DEV Community

Cover image for Store key-value data in Flutter using hive - but easier
Simon Pham
Simon Pham

Posted on

1

Store key-value data in Flutter using hive - but easier

Introduction

A while ago, I posted a post about how to store key-value data using shared_preferences package.

However, shared_preferences is not pure Dart and depends on the platform, which might not be a good performance choice. So, I decided to look for another approach, and I found hive.

After using the package for several projects, I grew tired of writing/copying boilerplate code just to store my key-value data. I came up with an idea of writing a wrapper package for hive. This package should meet these criteria:

  • Support data encryption
  • Support Lazy loading of data
  • Support store data using Enum key
  • Support Listenable
  • And be EASY to use.

Links

Guide to use:

You can either define your boxes as Singleton classes or use a service locator like
get_it
.

Let's take a look at the guide to define a simple SettingsBox to store your settings using singleton class approach.

1. Define box keys πŸ”‘

enum Settings {
  key, // Use as box key. You can use a String constant instead.

  /// Other keys below...
  themeMode,
  counter,
}
Enter fullscreen mode Exit fullscreen mode

2. Define a box πŸ“¦


import 'package:easy_hive/easy_hive.dart';

class SettingsBox extends EasyBox {
  @override
  String get boxKey => Settings.key.toString();

  /// Singleton.
  static final SettingsBox _instance = SettingsBox._();

  factory SettingsBox() => _instance;

  SettingsBox._();
}

Enter fullscreen mode Exit fullscreen mode

3. Initialize box πŸš€


import 'package:easy_hive/easy_hive.dart';

Future<void> main() async {
  await EasyBox.initialize();

  await SettingsBox().init();

  // runApp...
}

Enter fullscreen mode Exit fullscreen mode

4. Define getter & setter for your data πŸ’„

extension GeneralSettingsExtension on SettingsBox {
  ThemeMode get themeMode {
    final index = get(
      Settings.themeMode,
      defaultValue: 0,
    );
    return ThemeMode.values[index];
  }

  set themeMode(ThemeMode value) => put(Settings.themeMode, value.index);

  int get counter => get(Settings.counter, defaultValue: 0);

  set counter(int value) => put(Settings.counter, value);
}
Enter fullscreen mode Exit fullscreen mode

5. Use it anywhere πŸ”₯

  Text(
    'You have pushed: ${SettingsBox().counter} times.',
    style: Theme.of(context).textTheme.headlineMedium,
  ),
  FilledButton(
    onPressed: () {
      SettingsBox().counter++;
    },
    child: Text('Increment'),
  ),
  FilledButton(
    onPressed: () {
      SettingsBox().themeMode = ThemeMode.dark;
    },
    child: Text('Dark Theme'),
  ),
Enter fullscreen mode Exit fullscreen mode

Advanced Usage 😈

Enable encryption πŸ”

1. Install easy_hive_encryption:

2. Add EncryptionMixin to your box class:

class SettingsBox extends EasyBox with EncryptionMixin {
  @override
  String get boxKey => Settings.key.toString();

  /// Override encryption key name (optional).
  @override
  String get encryptionKeyName => "your-own-key-name";
}
Enter fullscreen mode Exit fullscreen mode

3. Follow flutter_secure_storage's guide for specific platform setup.

Enable lazy loading 🐒

1. Add LazyMixin to your box class:

class SettingsBox extends EasyBox with LazyMixin {
  @override
  String get boxKey => Settings.key.toString();
}
Enter fullscreen mode Exit fullscreen mode

2. Use await to get your value:

extension GeneralSettingsExtension on SettingsBox {
  Future<ThemeMode> getThemeMode() async {
    final index = await get(
      Settings.themeMode,
      defaultValue: 0,
    );
    return ThemeMode.values[index];
  }
}
Enter fullscreen mode Exit fullscreen mode

Listen to value changes 🎧

Recommended: Use RefreshableBox + provider:

1. Extends RefreshableBox instead of EasyBox:

class SettingsBox extends RefreshableBox {
  @override
  String get boxKey => Settings.key.toString();
}
Enter fullscreen mode Exit fullscreen mode

2. Use it as a provider:

  ChangeNotifierProvider(
    create: (_) => SettingsBox(),
    child: SomeWidget(),
  ),
Enter fullscreen mode Exit fullscreen mode
// Inside SomeWidget.
Text(
  'You have pushed: '
  '${context.select((SettingsBox _) => _.counter)} times.',
),
Enter fullscreen mode Exit fullscreen mode

For more info, see provider package.


Or if you don't want RefreshableBox:

Just use ValueListenableBuilder to listen to changes.

ValueListenableBuilder(
  valueListenable: [
    Settings.counter,
  ].of(SettingsBox()),
  builder: (context, _, __) {
    return Text(
      '${SettingsBox().counter}',
    );
  },
),
Enter fullscreen mode Exit fullscreen mode

This guide is taken from easy_hive repository.

Happy Coding 🦊

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay