There are many cases where you need to store data locally on users’ devices instead of using remote cloud servers or APIs. For example, you may need to persist data across app launches or download a language dictionary from the internet and save it for later offline use. This article will walk you through several solutions to do that.
Using Text/CSV/JSON files
The most common file types used for saving data are TXT, CSV, and JSON. You can use one or some of them for your applications. The location to place the data files is the Documents directory of a device. On Android, it is the AppData directory, and on iOS, it is NSDocumentDirectory.
To get the path correctly, we can use a package named path_provider.
Sample code:
Future<String> get _getLocalPath async {
final dir = await getApplicationDocumentsDirectory();
return dir.path;
}
Exiting the application, restarting, or shutting down the device does not cause losing data. Data is only deleted when the corresponding application is deleted.
See also:
- Flutter: How to Read and Write Text Files
- Flutter: Load and display content from CSV files
- How to encode/decode JSON in Flutter
SQLite
SQLite is a C-language library that implements a small, fast, self-contained, high-reliability, full-featured SQL database engine. It is built into all mobile phones and comes bundled with countless other applications that people use every day.
SQLite queries can be confusing for people who are new to them, but using SQLite will help you easily perform the operations of INSERT, READ, UPDATE, and DELETE with large amounts of data.
In Flutter, you can interact with SQLite by using the sqflite plugin (the name contains an “f” character). Below is an example of an UPDATE query:
int count = await database.rawUpdate(
'UPDATE Test SET name = ?, value = ? WHERE name = ?',
['updated name', '9876', 'some name']);
Besides the widely-used sqflite, there’re a couple of excellent packages for working with SQLite, such as drift and floor.
For more details on using SQLite in Flutter, see this article: Flutter & SQLite: CRUD Example.
Hive Database
If you have worked with MongoDB before then, you will probably enjoy using the HIVE database. This is a fast, lightweight, NoSQL key-value database written in pure Dart. You can work it just like a map:
var box = Hive.box('myBox');
box.put('name', 'David');
var name = box.get('name');
print('Name: $name');
Generally, using the Hive database is more simple and more flexible than using SQLite. You can learn how to perform CRUD operations with Hive and Flutter in this article: Flutter & Hive Database: CRUD Example.
Shared Preferences Storage
Shared preferences is a popular plugin that provides platform-specific persistent storage for simple data (NSUserDefaults on iOS and macOS, SharedPreferences on Android). Data may be persisted to disk asynchronously, and there is no guarantee that writes will be persisted to disk after returning, so this plugin must not be used for storing critical data.
Sample usage:
SharedPreferences prefs = await SharedPreferences.getInstance();
// Reading data
String name = prefs.getString('name');
// Updating
await prefs.setString('name', 'Some Value');
See our tutorials about using share preference for more details:
- How to locally save data in Flutter using shared_preferences
- Flutter: Save Icon to Database, File, Shared Preferences
Objectbox
Similar to Hive, Objectbox is a Dart-native key-value database. It’s extremely fast, improves response rates, and enables real-time applications. The database supports Android, iOS, macOS, Linux, and Windows and delivers built-in object links/relationships.
Objectbox is relatively young, and it needs time to mature and be battle-tested in large projects.
Here is a quick example:
@Entity()
class Person {
int id;
String firstName;
String lastName;
Person({this.id = 0, required this.firstName, required this.lastName});
}
final store = await openStore();
final box = store.box<Person>();
var person = Person(firstName: 'John', lastName: 'Doe');
final id = box.put(person); // Create
person = box.get(id)!; // Read
person.lastName = "Doe Doe Doe";
box.put(person); // Update
box.remove(person.id);
Realm Database
Realm is an open-source mobile-first database that can be used in Flutter to persist data offline. It’s developed and maintained by the company behind MongoDB, a super popular key-value, NoSQL database management system.
You can Realm to your Flutter project by running:
flutter pub add realm
Realm brings to the table its object-oriented data model, which you can use to define your data structure easily, like this:
import 'package:realm/realm.dart';
part 'app.g.dart';
// define a data model class named _User
@RealmModel()
class _User {
late String emal;
late String name;
int? age = 18;
}
Then you can generate RealmObject class User just by executing this command:
flutter pub run realm generate
Now you can create and save a new user to your Realm database as shown below:
var config = Configuration.local([User.schema]);
var realm = Realm(config);
var userOne = User("[email protected]", "Mr. Hello", age: 100);
realm.write(() {
realm.add(userOne);
});
Wrapping Up
This article introduces the most popular offline data storage methods today in Flutter applications. You can see more detailed instructions and examples in the following articles:
- Flutter: How to Read and Write Text Files
- Flutter: Load and display content from CSV files
- Flutter and Firestore Database: CRUD example
- Flutter + Firebase Storage: Upload, Retrieve, and Delete files
- How to encode/decode JSON in Flutter
- Flutter StreamBuilder examples (null safety)
You can also check out our Flutter topic page or Dart topic page for the latest tutorials and examples.