ObjectBox is a high-performance NoSQL database for mobile applications that is designed to be fast, efficient, and easy to use. It fits perfectly into Flutter projects, helping developers persist data locally with minimal boilerplate. Whether you’re building an offline-first app or just need local data storage, ObjectBox provides a powerful, reactive solution. In this guide, we will walk through how to set up ObjectBox in Flutter, explain how it works, and include code examples for you to follow.
What is ObjectBox, and Why Should You Use It?
ObjectBox is a database that works with objects, which means you don’t need to write SQL queries to interact with your data. It supports high-speed reads and writes and is optimized for mobile, making it a popular choice for developers building mobile apps that require offline capabilities or need to manage large amounts of local data.
ObjectBox’s key advantages include:
- Speed: ObjectBox is up to 10x faster than SQLite.
- Ease of Use: It works directly with Dart objects, reducing the need for complex data transformations.
- Scalability: ObjectBox is designed to scale as your app grows, capable of handling large datasets.
- Reactive Streams: It has built-in support for reactive data streams, which is perfect for Flutter apps that require real-time updates.
Let’s start by setting up ObjectBox in your Flutter project.
How to Set Up ObjectBox in a Flutter Project
To begin, you’ll need to add ObjectBox to your Flutter project. Here are the steps to get it up and running:
1. Add Dependencies
First, add the ObjectBox dependencies to your pubspec.yaml
file:
-
objectbox_flutter_libs:
Provides the necessary ObjectBox libraries for Flutter, enabling high-performance local data storage on mobile devices. To get the dependency click here. -
objectbox:
The core ObjectBox package that offers NoSQL database features, including efficient object persistence and database operations. To get the dependency click here. -
objectbox_generator:
A code generation tool that automatically generates ObjectBox binding code from your Dart model classes with annotations like@Entity
. To get the dependency click here. -
build_runner:
A command-line tool used for generating code in Flutter projects, such as running the ObjectBox code generator for model classes. To get the dependency click here.
dependencies:
objectbox_flutter_libs: ^4.0.3
objectbox: ^4.0.3
objectbox_generator: ^4.0.3
build_runner: ^2.4.13
Run flutter pub get
to install the packages.
flutter pub get
2. Set Up ObjectBox Model Classes
ObjectBox works with Dart objects, so you need to define the classes that will be stored in the database. Use annotations to define your entities.
import 'package:objectbox/objectbox.dart';
// Define an entity
@Entity()
class Task {
int id = 0; // 'id' will be automatically set by ObjectBox
String title;
bool isCompleted;
Task({required this.title, this.isCompleted = false});
}
In the example above, @Entity()
defines the Task
class as a database entity. The id
field is automatically set by ObjectBox, and the other fields represent the data attributes.
3. Generate ObjectBox Code
Once you’ve defined your entities, you need to generate the ObjectBox binding code. Use the following command to generate it:
flutter pub run build_runner build
This command generates all the necessary ObjectBox-related code in the background.
4. Initialize ObjectBox
Next, initialize ObjectBox in your app. Typically, this is done when the app starts.
import 'package:flutter/material.dart';
import 'objectbox.g.dart'; // Automatically generated file
late Store store; // The Store manages the ObjectBox database
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize ObjectBox
store = await openStore();
runApp(MyApp());
}
In this example, openStore()
initializes the database and prepares it for use. The store
variable represents the connection to the ObjectBox database and should be accessible throughout your app.
How to Perform CRUD Operations in ObjectBox
Now that ObjectBox is set up, let’s explore how to perform basic CRUD (Create, Read, Update, Delete) operations.
1. Creating Data (Inserting)
To insert data into the database, use the put()
function. Here’s how to add a new Task
:
void addTask(String title) {
final taskBox = store.box<Task>(); // Access the Task box
final newTask = Task(title: title);
taskBox.put(newTask); // Insert the task into ObjectBox
print('Task added: ${newTask.title}');
}
In this example, box<Task>()
is used to access the Task
box (a box is like a table in SQL databases). The put()
method inserts the task into the database.
2. Reading Data (Querying)
You can retrieve data from ObjectBox using the get()
function or by querying the database. Here’s how to retrieve all tasks:
List<Task> getAllTasks() {
final taskBox = store.box<Task>();
return taskBox.getAll(); // Get all tasks from the database
}
This function returns a list of all Task
objects stored in the database.
3. Updating Data
To update a record, you modify the object and use put()
again. ObjectBox will automatically update the record if the id
matches an existing record.
void updateTask(int id, bool isCompleted) {
final taskBox = store.box<Task>();
final task = taskBox.get(id);
if (task != null) {
task.isCompleted = isCompleted;
taskBox.put(task); // Update the task
print('Task updated: ${task.title}');
}
}
4. Deleting Data
To delete a task, use the remove()
function and pass the id
of the object you want to delete:
void deleteTask(int id) {
final taskBox = store.box<Task>();
taskBox.remove(id); // Remove task from the database
print('Task deleted with id: $id');
}
This deletes the task with the specified id
from the database.
Using Reactive Queries in ObjectBox
One of the most powerful features of ObjectBox is its reactive query support. This allows you to listen for changes in the data and automatically update your UI. In Flutter, you can use StreamBuilder
for this.
Here’s an example of how to use reactive queries with ObjectBox:
Stream<List<Task>> getTasksStream() {
final taskBox = store.box<Task>();
final query = taskBox.query().watch(triggerImmediately: true);
return query.map((query) => query.find());
}
You can then use StreamBuilder
in your UI to reactively display the tasks:
StreamBuilder<List<Task>>(
stream: getTasksStream(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
final tasks = snapshot.data ?? [];
return ListView.builder(
itemCount: tasks.length,
itemBuilder: (context, index) {
final task = tasks[index];
return ListTile(
title: Text(task.title),
trailing: Icon(
task.isCompleted ? Icons.check_box : Icons.check_box_outline_blank,
),
);
},
);
},
)
In this example, whenever the data in the Task
box changes, the StreamBuilder
will rebuild the widget, ensuring that the UI is always in sync with the data.
Conclusion
ObjectBox provides a powerful and efficient way to handle local data storage in Flutter. From its ease of use to the high performance it offers, it’s a great option for developers building apps that require data persistence. In this guide, we’ve covered how to set up ObjectBox, create data models, and perform CRUD operations. With reactive streams, you can keep your UI up to date automatically, making it a perfect fit for Flutter’s reactive architecture.
Happy Coding…!!!
Leave a Reply