Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Play ButtonPause Button
Tentang Anak Tech Team profile imageEdo Lubis
Edo Lubis forTentang Anak Tech Team

Posted on

     

Data persistence in flutter

When you develop an application, usually, the data used to display information originates from the internet. However, there are scenarios where the data from the internet needs to be stored somewhere on your local device. This can be for functionality purposes or to enhance performance and user experience while using the application.

Take the Facebook application as an example: when you open the main page or page detail, then close the application and reopen it, you will find yourself on the last visited page, and the page immediately displays data as if there were no loading process. This can happen because the data is stored locally, and when the application is opened, it uses the stored data to display the main or page detail while loading data from the internet to get the latest information.

In Flutter itself, there are many libraries designed to store data on the local device. In this article, I will share How to persist data using the best libraries (in my opinion) for storing data locally in Flutter.

1. shared_preferences
shared_preferences is a plugin for reading and writing simple key-value pairs. It uses NSUserDefaults on iOS and SharedPreferences on Android. shared_preferences is a best choice for storing small and non-sensitive data, such as theme preferences, language settings, settings.

implementation example:
write data

Future<void> saveTheme(bool isLightMode) async {    final SharedPreferences prefs = await SharedPreferences.getInstance();    await prefs.setBool('isLightMode', isLightMode);}
Enter fullscreen modeExit fullscreen mode

Read data

Future<bool?> readTheme() async {    final SharedPreferences prefs = await SharedPreferences.getInstance();    final bool? isLightMode = prefs.getBool('isLightMode');    return isLightMode;}
Enter fullscreen modeExit fullscreen mode

Delete data

Future<void> deleteTheme() async {    final SharedPreferences prefs = await SharedPreferences.getInstance();    await prefs.remove('isLightMode');}
Enter fullscreen modeExit fullscreen mode

SharedPreferences is limited to only supporting certain data types like int, double, bool, String, and List. However, we can store objects in SharedPreferences by converting them into a string. One common way to do this is by using JSON. We can convert an object to a JSON string when saving it and then convert it back to an object when retrieving it.

implementation example:

class Setting {  bool? isLightMode;  String? lang;  int? counter;  Setting({this.isLightMode, this.lang, this.counter});  Setting.fromJson(Map<String, dynamic> json) {    isLightMode = json['isLightMode'];    lang = json['lang'];    counter = json['counter'];  }  Map<String, dynamic> toJson() {    final Map<String, dynamic> data = <String, dynamic>{};    data['isLightMode'] = isLightMode;    data['lang'] = lang;    data['counter'] = counter;    return data;  }}
Enter fullscreen modeExit fullscreen mode
  Future<void> saveSetting(Setting setting) async {    final SharedPreferences prefs = await SharedPreferences.getInstance();    await prefs.setString('setting', jsonEncode(setting.toJson()));  }  Future<Setting?> readSetting() async {    final SharedPreferences prefs = await SharedPreferences.getInstance();    final String? json = prefs.getString('setting');    if (json == null) return null;    return Setting.fromJson(jsonDecode(json));  }  Future<void> deleteSetting() async {    final SharedPreferences prefs = await SharedPreferences.getInstance();    await prefs.remove('setting');  }
Enter fullscreen modeExit fullscreen mode

2. sqflite
sqflite is a Flutter plugin that provides access to SQLite, a lightweight, serverless relational database commonly used in mobile applications for local data storage. Sqflite is a popular choice for applications requiring local data storage with more complex and relational structures.
implementation example:

class Item {  final int id;  final String title;  final String description;  const Item({    required this.title,    required this.description,    required this.id,  });  factory Item.fromJson(Map<String, dynamic> json) => Item(        id: json['id'],        title: json['title'],        description: json['description'],      );  Map<String, dynamic> toJson() => {        'id': id,        'title': title,        'description': description,      };}
Enter fullscreen modeExit fullscreen mode
class DatabaseHelper {  static const int _version = 1;  static const String _dbName = "items.db";  static Future<Database> _getDB() async {    return openDatabase(      join(await getDatabasesPath(), _dbName),      onCreate: (db, version) async => await db.execute(          "CREATE TABLE Item(id INTEGER PRIMARY KEY, title TEXT NOT NULL, description TEXT NOT NULL);"),      version: _version,    );  }  static Future<int> addItem(Item item) async {    final db = await _getDB();    return await db.insert("Item", item.toJson(),        conflictAlgorithm: ConflictAlgorithm.replace);  }  static Future<int> updateItem(Item item) async {    final db = await _getDB();    return await db.update(      "Item",      item.toJson(),      where: 'id = ?',      whereArgs: [item.id],      conflictAlgorithm: ConflictAlgorithm.replace,    );  }  static Future<int> deleteItem(Item item) async {    final db = await _getDB();    return await db.delete(      "Item",      where: 'id = ?',      whereArgs: [item.id],    );  }  static Future<List<Item>?> getAllItems() async {    final db = await _getDB();    final List<Map<String, dynamic>> maps = await db.query("Item");    if (maps.isEmpty) return null;    return List.generate(maps.length, (index) => Item.fromJson(maps[index]));  }}
Enter fullscreen modeExit fullscreen mode

3. hive
Hive is a key-value database written in Dart. Hive excels in write and delete operations compared to SQLite and SharedPreferences, and it is on par with SharedPreferences in read performance, while SQLite is significantly slower. Hive has built-in encryption using AES-256, making it suitable for storing sensitive data.
implementation example:

Future<void> saveUser(Map<String, dynamic> user) async {  var box = await Hive.openBox('myBox');  await box.put('user', user);}Future<Map<String, dynamic>?> readUser() async {  var box = await Hive.openBox('myBox');  final Map<String, dynamic>? json = box.get('user');  return json;}Future<void> deleteUser() async {  var box = await Hive.openBox('myBox');  await box.delete('user');}
Enter fullscreen modeExit fullscreen mode

If your project uses theflutter_bloc library for state management, you can easily cache data locally using Hive. The creator of flutter_bloc has developed thehydrated_bloc library, which includes HydratedStorage that comes with Hive implemented.

void main() async {  WidgetsFlutterBinding.ensureInitialized();  HydratedBloc.storage = await HydratedStorage.build(    storageDirectory: kIsWeb        ? HydratedStorage.webStorageDirectory        : await getTemporaryDirectory(),  );  runApp(const MyApp());}
Enter fullscreen modeExit fullscreen mode
class UserCubit extends HydratedCubit<User?> {  UserCubit() : super(null);  void login(User user) => emit(user);  @override  User? fromJson(Map<String, dynamic> json) =>      json['user'] != null ? User.fromJson(json['user']) : null;  @override  Map<String, dynamic> toJson(User? state) => {'user': state};}
Enter fullscreen modeExit fullscreen mode

4. isar
Isar was created by the creator of Hive to overcome some limitations present in Hive and to offer a more advanced and efficient solution for local data storage in Flutter and Dart applications.

Isar is a fast, cross-platform NoSQL database that is well-integrated with Flutter and Dart. It is designed to provide high performance and ease of use.
implementation example:

dependencies:  flutter:    sdk: flutter  isar: ^2.5.0  isar_flutter_libs: ^2.5.0dev_dependencies:  flutter_test:    sdk: flutter  build_runner: ^2.2.0  isar_generator: ^2.5.0
Enter fullscreen modeExit fullscreen mode
part 'isar_page.g.dart';@Collection()class Post {  int id = Isar.autoIncrement;  late String title;  late DateTime date;}
Enter fullscreen modeExit fullscreen mode

run flutter pub run build_runner

late Isar isar;@overridevoid initState() {  super.initState();  openInstance();}void openInstance() async {  final dir = await getApplicationSupportDirectory();  isar = await Isar.open(    schemas: [PostSchema],    directory: dir.path,    inspector: true,  );}void readPost() async {  final posts = await isar.posts      .filter()      .titleContains('awesome', caseSensitive: false)      .sortByDateDesc()      .limit(10)      .findAll();  print(posts);}void createPost() async {  final newPost = Post()    ..title = 'awesome new database'    ..date = DateTime.now();  await isar.writeTxn((isar) async {    newPost.id = await isar.posts.put(newPost);  });}
Enter fullscreen modeExit fullscreen mode

5. flutter_secure_storage
If you want to store sensitive data, thenflutter_secure_storage is one of the best solutions. flutter_secure_storage is a Flutter package that provides a secure way to store sensitive data on the device, using Keychain on iOS and a KeyStore based solution on Android.
implementation example:

class Auth {  String? token;  String? id;  Auth({this.token, this.id});  Auth.fromJson(Map<String, dynamic> json) {    token = json['token'];    id = json['id'];  }  Map<String, dynamic> toJson() {    final Map<String, dynamic> data = <String, dynamic>{};    data['token'] = token;    data['id'] = id;    return data;  }}
Enter fullscreen modeExit fullscreen mode
  final storage = const FlutterSecureStorage();  Future<void> saveAuth(Auth auth) async {    await storage.write(key: 'auth', value: jsonEncode(auth.toJson()));  }  Future<Auth?> readAuth() async {    final String? json = await storage.read(key: 'auth');    if (json == null) return null;    return Auth.fromJson(jsonDecode(json));  }  Future<void> deleteAuth() async {    await storage.delete(key: 'auth');  }
Enter fullscreen modeExit fullscreen mode

6. get_storage
If you're using GetX as state management, then you might be familiar withget_storage. get_storage is a local data storage package developed by the GetX team for Flutter. It's a lightweight and easy-to-use storage solution, allowing you to persistently store data in key-value pairs on the user's device.
implementation example:

class User {  String? name;  String? id;  User({this.name, this.id});  User.fromJson(Map<String, dynamic> json) {    name = json['name'];    id = json['id'];  }  Map<String, dynamic> toJson() {    final Map<String, dynamic> data = <String, dynamic>{};    data['name'] = name;    data['id'] = id;    return data;  }}
Enter fullscreen modeExit fullscreen mode
final box = GetStorage();Future<void> saveUser(User user) async {  await box.write('user', jsonEncode(user.toJson()));}User? readUser() {  final String? json = box.read('user');  if (json == null) return null;  return User.fromJson(jsonDecode(json));}Future<void> deleteUser() async {  await box.remove('user');}
Enter fullscreen modeExit fullscreen mode

get_storage is well-suited for applications with simple and fast data storage needs. However, for more complex requirements such as indexing or ensuring disk write confirmation, it's recommended to consider using sqflite, Hive, isar, etc.

Conclusion
There are the best libraries for persist data locally, The usage of the library typically depends on the type of data being stored, whether it is sensitive data, data with relationships, or just simple API responses.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Tech for Tomorrow's Growth: Enhancing Child Development

Tentang Anak's tech team Focused on developing reliable solutions for child development. Experienced supporting the company's mission in early childhood technology.

More fromTentang Anak Tech Team

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp