When developing Flutter applications, storing data locally is often necessary for various reasons, such as caching user preferences, managing app state, or persisting data offline. Flutter provides several options for local data storage, with SharedPreferences
and Hive
being two popular choices. This blog post will compare Hive
and SharedPreferences
, highlighting their differences, advantages, and disadvantages, to help you choose the right one for your project.
Introduction to SharedPreferences
SharedPreferences
is a simple storage solution that allows you to store key-value pairs of primitive data types: booleans, integers, doubles, and strings. It is suitable for storing small amounts of simple data like user preferences, settings, or flags.
Introduction to Hive
Hive
is a lightweight, NoSQL database written in pure Dart. It is designed to be fast, easy to use, and fully cross-platform, supporting mobile, desktop, and web. Hive allows you to store more complex data structures and offers features like encryption and lazy loading.
Key Differences
Here’s a comparison table highlighting the key differences between SharedPreferences
and Hive
:
Feature | SharedPreferences | Hive |
---|---|---|
Data Types | Primitives (bool, int, double, String) | Any Dart object (supports custom classes) |
Data Size | Small amounts of simple data | Larger and more complex data |
Performance | Synchronous, can cause UI blocking | Asynchronous, non-blocking UI |
Complexity | Very simple to use | More features, slightly more complex |
Storage Format | XML (on Android) or Plist (on iOS) | Binary format |
Queries | Not supported | Supported through indexes |
Encryption | Not supported by default | Built-in support for encryption |
When to Use SharedPreferences
SharedPreferences
is ideal when:
- You need to store a small amount of primitive data.
- Simplicity and ease of use are more important than performance or data complexity.
- Data doesn’t need to be queried or indexed.
- Encryption is not a requirement.
Example of Using SharedPreferences
First, add the shared_preferences
package to your pubspec.yaml
:
dependencies:
shared_preferences: ^2.2.2
Then, use SharedPreferences
to save and retrieve data:
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreferencesService {
static Future saveString(String key, String value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(key, value);
}
static Future getString(String key) async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(key);
}
static Future saveBool(String key, bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(key, value);
}
static Future getBool(String key) async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool(key);
}
static Future remove(String key) async {
final prefs = await SharedPreferences.getInstance();
prefs.remove(key);
}
}
// Usage
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SharedPreferencesService.saveString('username', 'johndoe');
String? username = await SharedPreferencesService.getString('username');
print('Username: $username'); // Output: Username: johndoe
await SharedPreferencesService.saveBool('isDarkMode', true);
bool? isDarkMode = await SharedPreferencesService.getBool('isDarkMode');
print('Is Dark Mode: $isDarkMode'); // Output: Is Dark Mode: true
}
When to Use Hive
Hive
is ideal when:
- You need to store larger amounts of data or complex objects.
- Performance is critical.
- You need to query or index your data.
- Encryption is required for sensitive data.
- You want a solution that supports desktop and web in addition to mobile.
Example of Using Hive
First, add the hive
and hive_flutter
packages to your pubspec.yaml
:
dependencies:
hive: ^2.2.3
hive_flutter: ^1.1.2
And add build_runner
and hive_generator
to your dev_dependencies
for code generation:
dev_dependencies:
build_runner: ^2.4.8
hive_generator: ^2.0.1
Create a Hive object (requires type adapter. We are going to generate this) :
import 'package:hive/hive.dart';
part 'user.g.dart';
@HiveType(typeId: 0)
class User {
@HiveField(0)
String name;
@HiveField(1)
int age;
@HiveField(2)
String email;
User({required this.name, required this.age, required this.email});
}
Run flutter pub run build_runner build
in the terminal to generate type adapter: user.g.dart
file. Don’t forget to import this in wherever you want to use your Hive model.
Then, use Hive
to save and retrieve data:
import 'package:flutter/widgets.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'user.dart'; // generated user model
class HiveService {
static Future initializeHive() async {
await Hive.initFlutter();
Hive.registerAdapter(UserAdapter());
}
static Future saveUser(User user) async {
var box = await Hive.openBox('usersBox');
await box.put(user.email, user);
}
static Future getUser(String email) async {
var box = await Hive.openBox('usersBox');
return box.get(email);
}
static Future deleteUser(String email) async {
var box = await Hive.openBox('usersBox');
await box.delete(email);
}
static Future> getAllUsers() async {
var box = await Hive.openBox('usersBox');
return box.values.toList();
}
static Future clearAllUsers() async {
var box = await Hive.openBox('usersBox');
await box.clear();
}
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await HiveService.initializeHive();
// Usage
final user = User(name: 'John Doe', age: 30, email: 'john.doe@example.com');
await HiveService.saveUser(user);
User? retrievedUser = await HiveService.getUser('john.doe@example.com');
print('Retrieved User: ${retrievedUser?.name}, ${retrievedUser?.age}, ${retrievedUser?.email}');
// Retrieved User: John Doe, 30, john.doe@example.com
await HiveService.clearAllUsers();
}
Pros and Cons
SharedPreferences
- Pros:
- Very simple and easy to use.
- Suitable for small amounts of data.
- Cons:
- Only supports primitive data types.
- Synchronous, can cause UI blocking.
- No built-in encryption.
Hive
- Pros:
- Supports any Dart object.
- Asynchronous, non-blocking operations.
- Built-in encryption.
- Supports indexes and queries.
- Cross-platform support (mobile, desktop, web).
- Cons:
- More complex to set up than
SharedPreferences
. - Larger dependency size compared to
SharedPreferences
.
- More complex to set up than
Conclusion
Choosing between SharedPreferences
and Hive
depends on the requirements of your Flutter application. If you need to store small amounts of simple data and prioritize ease of use, SharedPreferences
is a good choice. However, if you need to store larger amounts of complex data, require better performance, or need features like encryption and querying, Hive
is the more suitable option.
By understanding the strengths and limitations of each solution, you can make an informed decision that optimizes your app’s performance and data management.