Getting started

ObjectBox is a super fast mobile database that persists objects. It lets you avoid many repetitive tasks and offers a simple interface to your data.

Add ObjectBox to your project

Java/Kotlin (Android)
Java/Kotlin (Desktop)
Flutter
Dart
Java/Kotlin (Android)
Video Tutorial on Getting Started with ObjectBox for Android and Java

ObjectBox is available from the Central repository. To add ObjectBox to your Android project, open the root build.gradle file of your project (not the ones for your app or module) and add a global variable for the version and the ObjectBox Gradle plugin:

buildscript {
ext.objectboxVersion = '2.9.1'
repositories {
mavenCentral()
// Note: 2.9.0 and older are available on jcenter()
}
dependencies {
// Android Gradle Plugin 3.2.1 or later supported.
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "io.objectbox:objectbox-gradle-plugin:$objectboxVersion"
}
}

Open the build.gradle file for your app or module and, after the com.android.application plugin, apply the io.objectbox plugin:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' // Only for Kotlin projects.
apply plugin: 'kotlin-kapt' // Only for Kotlin projects.
apply plugin: 'io.objectbox' // Apply last.

If you encounter any problems in this or later steps, check out the FAQ and Troubleshooting pages.

Then do "Sync Project with Gradle Files" in Android Studio so the Gradle plugin automatically adds the required ObjectBox libraries and code generation tasks.

Optional: Advanced Setup

The ObjectBox plugin uses reasonable defaults and detects most configurations automatically. However, if needed you can configure the model file path, the MyObjectBox package, enable debug mode and more using advanced setup options.

Java/Kotlin (Desktop)

ObjectBox for Java supports plain Java or Kotlin projects. See the following page on how to add ObjectBox to a plain Java project.

Flutter

Add these dependencies to your pubspec.yaml:

dependencies:
objectbox: ^0.15.0
objectbox_flutter_libs: any
# for ObjectBox Sync use this dependency instead:
# objectbox_sync_flutter_libs: any
dev_dependencies:
build_runner: ^1.0.0
objectbox_generator: any

Then install the packages: flutter pub get

For XCode/iOS only: increase the deployment target to iOS 11 and, under Architectures, replace ${ARCHS_STANDARD} with arm64 (or $ARCHS_STANDARD_64_BIT). See FAQ for details.

Dart

Add these dependencies to your pubspec.yaml:

dependencies:
objectbox: ^0.15.0
dev_dependencies:
build_runner: ^2.0.0
objectbox_generator: any

Install the packages: dart pub get

Install objectbox-c system-wide (use "Git bash" on Windows):

bash <(curl -s https://raw.githubusercontent.com/objectbox/objectbox-dart/main/install.sh)

To install ObjectBox Sync variant of the native library, pass --sync argument to the script:

bash <(curl -s https://raw.githubusercontent.com/objectbox/objectbox-dart/main/install.sh) --sync

Define Entity Classes

Next, define your model by annotating at least one class with @Entity and @Id. A simple entity representing a user could look like this:

Java
Kotlin
Dart
Java
User.java
@Entity
public class User {
@Id
public long id;
public String name;
}
Kotlin
models.kt
@Entity
data class User(
@Id
var id: Long = 0,
var name: String? = null
)

When using a data class, add default values for all parameters. This will ensure your data class will have a constructor that can be called by ObjectBox. (Technically this is only required if adding properties to the class body, like custom or transient properties or relations, but it's a good idea to do it always.)

Dart
models.dart
()
class User {
int id = 0;
String? name;
)

Entities must have one ID property of type long (or Long in Kotlin, int in Dart). If you need to use other types, like a String ID, see the @Id annotation docs. Also, it must have non-private visibility (or non-private getter and setter methods).

Entities must also have a no-args constructor, or for better performance, a constructor with all properties as arguments. In the above example, a default, no-args constructor is generated by the compiler.

For a deeper explanation and a look at all other available annotations (e.g. for relations and indexes) check the Entity Annotations page.

Generate ObjectBox code

Java/Kotlin
Flutter
Dart
Java/Kotlin

Build your project to generate the classes required to use ObjectBox, for example using Build > Make Project in Android Studio.

Note: If you make significant changes to your entities, e.g. by moving them or modifying annotations, make sure to rebuild the project so generated ObjectBox code is updated.

Flutter

Run flutter pub run build_runner build to generate the binding code required to use ObjectBox.

ObjectBox generator will look for all @Entity annotations in your lib folder and create a single database definition lib/objectbox-model.json and supporting code in lib/objectbox.g.dart

Add objectbox.g.dart to your version control ignore list (e.g. .gitignore), otherwise build_runner will complain about it being changed each time you pull a change.

Dart

Run dart run build_runner build to generate the binding code required to use ObjectBox.

ObjectBox generator will look for all @Entity annotations in your lib folder and create a single database definition lib/objectbox-model.json and supporting code in lib/objectbox.g.dart

Add objectbox.g.dart to your version control ignore list (e.g. .gitignore), otherwise build_runner will complain about it being changed each time you pull a change.

Keep the Model file

Among other files ObjectBox generates a JSON model file, by default to app/objectbox-models/default.json for Android projects, or lib/objectbox-model.json for Dart/Flutter projects. This JSON file changes when you change your entity classes (or sometimes with a new version of ObjectBox).

Keep this JSON file, commit the changes to version control!

In Android Studio you might have to switch the Project view from Android to Project to see the default.json model file.

This file keeps track of unique IDs assigned to your entities and properties. This ensures that an older version of your database can be smoothly upgraded if your entities or properties change. It also enables you to keep data when renaming entities or properties or to resolve conflicts when two of your developers make changes at the same time.

Create a Store

BoxStore (Java) or Store (Dart) is the entry point for using ObjectBox. It is the direct interface to the database and manages Boxes. Typically, you want to keep a store open while your app is running.

Java (Android)
Kotlin (Android)
Flutter
Dart
Java (Android)

Create it using the builder returned by the generated MyObjectBox class, for example in a small helper class like this:

public class ObjectBox {
private static BoxStore boxStore;
public static void init(Context context) {
boxStore = MyObjectBox.builder()
.androidContext(context.getApplicationContext())
.build();
}
public static BoxStore get() { return boxStore; }
}

If you encounter UnsatisfiedLinkError or LinkageError on the build call, see App Bundle, split APKs and Multidex for solutions.

The best time to initialize ObjectBox is when your app starts. We suggest to do it in the onCreate method of your Application class:

public class ExampleApp extends Application {
@Override
public void onCreate() {
super.onCreate();
ObjectBox.init(this);
}
}
Kotlin (Android)

Create it using the builder returned by the generated MyObjectBox class, for example in a small helper class like this:

object ObjectBox {
lateinit var store: BoxStore
private set
fun init(context: Context) {
store = MyObjectBox.builder()
.androidContext(context.applicationContext)
.build()
}
}

If you encounter UnsatisfiedLinkError or LinkageError on the build call, see App Bundle, split APKs and Multidex for solutions.

The best time to initialize ObjectBox is when your app starts. We suggest to do it in the onCreate method of your Application class:

class ExampleApp : Application() {
override fun onCreate() {
super.onCreate()
ObjectBox.init(this)
}
}
Flutter

Create it using the generated getObjectBoxModel() method and getApplicationDocumentsDirectory() from the path_provider package, for example like this:

import 'package:path_provider/path_provider.dart';
import 'objectbox.g.dart'; // created by `flutter pub run build_runner build`
class _MyHomePageState extends State<MyHomePage> {
Store _store;
void initState() {
super.initState();
getApplicationDocumentsDirectory().then((Directory dir) {
// Note: getObjectBoxModel() is generated for you in objectbox.g.dart
_store = Store(getObjectBoxModel(), directory: dir.path + '/objectbox');
});
}
void dispose() {
_store?.close(); // don't forget to close the store
super.dispose();
}
}

On mobile devices/sandboxed apps, you should store data in your app documents directory - it stays there even when you close the app. See Flutter: read & write files for more info.

If you didn't specify the documents directory path to ObjectBox like above, it would try to use the default directory "objectbox" in the current working directory, but it doesn't have permissions to write there: failed to create store: 10199 Dir does not exist: objectbox (30).

Dart

Create it using the generated getObjectBoxModel() method, for example like this:

import 'objectbox.g.dart'; // created by `dart pub run build_runner build`
void main() {
// Note: getObjectBoxModel() is generated for you in objectbox.g.dart
final store = Store(getObjectBoxModel());
// your app code ...
store.close(); // don't forget to close the store
}

The above minimal example omits the argument to Store(directory: ), using the default - 'objectbox' in the current working directory.

Basic Box operations

The Box class is likely the class you interact with most. A Box instance gives you access to objects of a particular type. For example, if you have User and Order entities, you need a Box object to interact with each:

Java
Kotlin
Dart
Java
Box<User> userBox = ObjectBox.get().boxFor(User.class);
Box<Order> orderBox = ObjectBox.get().boxFor(Order.class);
Kotlin
val userBox = ObjectBox.store.boxFor(User::class.java)
val orderBox = ObjectBox.store.boxFor(Order::class.java)
Dart
final userBox = store.box<User>();
final orderBox = store.box<Order>();

These are some of the operations offered by the Box class:

put inserts a new object or updates an existing one (with the same ID). When inserting, an ID will be assigned to the just inserted object (this will be explained below) and returned. put also supports putting multiple objects, which is more efficient.

Java
Kotlin
Dart
Java
User user = new User("Tina");
userBox.put(user);
List<User> users = getNewUsers();
userBox.put(users);
Kotlin
val user = User("Tina")
userBox.put(user)
val users: List<User> = getNewUsers()
userBox.put(users)
Dart
final user = User(name: 'Tina');
userBox.put(user);
final users = getNewUsers();
userBox.putMany(users);

get and getAll: Given an object’s ID, get reads it from its box. To get all objects in the box use getAll .

Java
Kotlin
Dart
Java
User user = userBox.get(userId);
List<User> users = userBox.getAll();
Kotlin
val user = userBox[userId]
val users = userBox.all
Dart
final user = userBox.get(userId);
final users = userBox.getMany(userIds);
final users = userBox.getAll();

query: Starts building a query to return objects from the box that match certain conditions. See queries for details.

Java
Kotlin
Dart
Java
Query<User> query = userBox.query()
.equal(User_.name, "Tom")
.order(User_.name)
.build();
List<User> results = query.find();
query.close();
Kotlin
val query = userBox.query()
.equal(User_.name, "Tom")
.order(User_.name)
.build()
val results = query.find()
query.close()
Dart
final query =
(userBox.query(User_.name.equals('Tom'))..order(User_.name)).build();
final results = query.find();
query.close();

remove and removeAll: Remove a previously put object from its box (deletes it). remove also supports removing multiple objects, which is more efficient. removeAll removes (deletes) all objects in a box.

Java
Kotlin
Dart
Java
boolean isRemoved = userBox.remove(userId);
userBox.remove(users);
// alternatively:
userBox.removeByIds(userIds);
userBox.removeAll();
Kotlin
val isRemoved = userBox.remove(userId)
userBox.remove(users)
// alternatively:
userBox.removeByIds(userIds)
userBox.removeAll()
Dart
final isRemoved = userBox.remove(userId);
userBox.removeMany(userIds);
userBox.removeAll();

count: Returns the number of objects stored in this box.

Java
Kotlin
Dart
Java
long userCount = userBox.count();
Kotlin
val userCount = userBox.count()
Dart
final userCount = userBox.count();

For a complete list of methods available in the Box class, check the API reference documentation for Java or Dart.

Asynchronous operations

Only in Dart

putAsync: asynchronously inserts a new object or updates an existing one (with the same ID). The returned future completes when the object is successfully written to the database.

Dart
Dart
final user = User(name: 'Tina');
Future<int> idFuture = userBox.putAsync(user);
...
final id = await idFuture;
userBox.get(id); // after the future completed, the object is inserted

putQueued: Schedules the given object to be put later on, by an asynchronous queue, returns the id immediately even though the object may not have been written yet. You can use store's awaitAsyncCompletion() and awaitAsyncSubmitted() to wait for the async queue to finish.

Dart
Dart
for (int i = 0; i < 100; i++) {
userBox.putQueued(User(name: 'User $i'));
}
store.awaitAsyncSubmitted();
// after `awaitAsync*`: objects are inserted
expect(userBox.count(), equals(100));

Object IDs

By default IDs for new objects are assigned by ObjectBox. When a new object is put, it will be assigned the next highest available ID:

Java
Kotlin
Dart
Java
User user = new User();
// user.id == 0
box.put(user);
// user.id != 0
long id = user.id;
Kotlin
val user = User()
// user.id == 0
box.put(user)
// user.id != 0
val id = user.id
Dart
final user = User();
// user.id == 0
box.put(user);
// user.id != 0
final id = user.id;

For example, if there is an object with ID 1 and another with ID 100 in a box, the next new object that is put will be assigned ID 101.

If you try to assign a new ID yourself and put the object, ObjectBox will throw an error.

If you need to assign IDs by yourself, have a look at how to switch to self-assigned IDs and what side effects apply.

Reserved Object IDs

Object IDs can not be:

  • 0 (zero) or null (if using java.lang.Long) As said above, when putting an object with ID zero it will be assigned an unused ID (not zero).

  • 0xFFFFFFFFFFFFFFFF (-1 in Java) Reserved for internal use.

For a detailed explanation see the page on Object IDs.

Transactions

While ObjectBox offers powerful transactions, it is sufficient for many apps to consider just some basics guidelines about transactions:

  • A put runs an implicit transaction.

  • Prefer put bulk overloads for lists (like put(entities)) when possible.

  • For a high number of DB interactions in loops, consider explicit transactions, such as using runInTx().

For more details check the separate transaction documentation.

Have an app with greenDAO? DaoCompat is for you!

DaoCompat is a compatibility layer that gives you a greenDAO like API for ObjectBox. It makes switching from greenDAO to ObjectBox simple. Have a look at the documentation and the example. Contact us if you have any questions!

Next steps