Saving Data with an ObjectBox Database on Android

In this tutorial, you’ll learn about saving data with an ObjectBox database on Android. You’ll also learn about the different types of databases. By Subhrajyoti Sen.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 3 of this article. Click here to view the first page.

Adding ObjectBox to Your Project

First, you will need to add the dependency for ObjectBox to your project.
Open the project level build.gradle and add the following dependency inside the dependencies block:

classpath 'io.objectbox:objectbox-gradle-plugin:2.3.4'

Open the app level build.gradle and add the following line right before the android tag:

apply plugin: 'io.objectbox'

Be sure to sync your gradle files with the project.

Creating the Database Entry Structure

Since you want to store a list of borrowed items’ details, you first need to define the fields you want to store. This is the Entity and provides the database with the structure used to store data.

Open BorrowedItemModel.kt from the project. You can see a Kotlin data class:

data class BorrowedItemModel(
  var id: Long = 0,
  val itemName: String,
  val borrowerName: String,
  val borrowDate: String
)

Notice that only the id field is a var while the others are val. You’ll get back to that in a moment.

To tell ObjectBox that BorrowedItemModel is the Entity you want to store, you have to annotate it with @Entity as below:

@Entity
data class BorrowedItemModel(
    // declared fields
)

After you add the @Entity annotation, you can alt + enter on the annotation to get Android Studio to automatically add the necessary import statement for you.

ObjectBox needs a way to uniquely identify each Entity. This identifier needs to be a field of type Long. This is what the id field in BorrowedItemModel is for.

To make ObjectBox use id as the identifier, you need to annotate it with @Id as follows:

@Entity
data class BorrowedItemModel(
    @Id
    var id: Long = 0,
    // other declared fields
)

Build and run the app. While you won’t notice any difference, ObjectBox creates a file called BorrowedItemModel_.java that it’ll use internally.

Creating the BoxStore

To perform operations on the database, first you’ll need a BoxStore instance. You can think of it as a box where you store all the entities.

Create a file called ObjectBox.kt and add the following code to it:

object ObjectBox {

  lateinit var boxStore: BoxStore
    private set

  fun init(context: Context) {
    boxStore = MyObjectBox.builder()
      .androidContext(context.applicationContext)
      .build()
  }

}

This class creates and stores a single instance of BoxStore that’s accessible across the app. These types of classes are known as Singletons.

You have to initialize BoxStore once the app starts, which you can do with an Application class. The project already contains an Application class, BorrowApp.kt. Open it and add the following code at the end of the onCreate function:

ObjectBox.init(this)

This uses the Application Context to initialize BoxStore. BoxStore is tied to the entire app, not a single Activity. This is why you use an Application Context instead of an Activity Context.

Add Entities to the Database

Since you want to store entities from the new Activity, you’ll need a BoxStore instance. Open BorrowedItemActivity.kt and declare the following variable before onCreate:

private val borrowBox = ObjectBox.boxStore.boxFor(BorrowedItemModel::class.java)

This uses the BoxState singleton and gives access to a Box created specifically for storing BorrowedItemModel instances.

Now that everything is set, you have to extract the values from the input fields and add them to the database.

Add the following code inside fab.setOnClickListener lambda inside BorrwedItemActivity:

// 1
if (borrowed_item_name_edittext.text.isNullOrBlank() ||
  borrower_name_edittext.text.isNullOrBlank() ||
  borrow_date_textview.text.isNullOrBlank()) {
    Toast.makeText(this, "Please enter all the required fields", 
      Toast.LENGTH_SHORT).show()
} else {
  // 2
  val borrowedItem = BorrowedItemModel(
    itemName =  borrowed_item_name_edittext.text.toString(),
    borrowerName = borrower_name_edittext.text.toString(),
    borrowDate = borrow_date_textview.text.toString()
  )
  // 3
  borrowBox.put(borrowedItem)
  finish()
}

This code does a couple of things:

  1. First, the code verifies all the required fields.
  2. Then it creates a BorrowedItemModel instance with the entered values.
  3. Finally, it saves the item and finishes the Activity.

Remember how the id field was a var? It’s because you don’t manually set it.

ObjectBox internally generates an id and assigns it to the id field when an entity inserts into the database. borrowBox.put() puts an entity in the database.

Build and run the project. Notice that even though you’re storing the entity in the database, you can’t see it anywhere. That’s because there’s no write query yet.

Add entities to the database

Reading From the Database

Now MainActivity will need a Box for BorrowedItemModel. Add the following variable to MainActivity, as you did for BorrowedItemActivity:

private val borrowBox = ObjectBox.boxStore.boxFor(BorrowedItemModel::class.java)

Next, you need to create a Query instance so you can create a query. Add the following code right below borrowBox. When using alt + enter to automatically create the import, be sure to choose import io.objectbox.query.Query:

private lateinit var borrowQuery: Query<BorrowedItemModel>

This declares an instance of Query that’s performed on a Box for BorrowedItemModel.

Add the following code inside onCreate:

borrowQuery = borrowBox.query()
  .build()

This creates a query that fetches all the entities in the order of insertion. This is the read query.

Now that the query is ready, it needs to run every time anything changes in the database. Normally, this would be a messy task.

Luckily, each Query in ObjectBox is reactive. Reactive means it’s automatically called if anything in the database changes.

You need to subscribe to the query to get an updated list of entities. To do that, you first need to declare a DataSubscription instance. Add the following code before onCreate:

private lateinit var subscription: DataSubscription

Then, inside onCreate, below the other code you interted, add:

subscription = borrowQuery
  .subscribe()
  .on(AndroidScheduler.mainThread())
  .observer {notes -> borrowRecyclerViewAdapter.setBorrowedItemList(notes) }

AndroidScheduler.mainThread() specifies that the subscription happens on the Android main thread. This is because you can’t update the UI from a background thread.

Now every time the list of entities changes, the RecyclerViewAdapter is also updated.

When dealing with a subscription, always remember to cancel it when you no longer need it. This prevents memory leaks. To do this, add the cancellation logic in onDestroy:

subscription.cancel()

Build and run the project. You’ll notice that the item you previously added now shows up in the list.

the item you previously added now shows up in the list

Editing an Entity

To edit an Entity, you need access to its id. So, the id needs to be passed to the editing Activity. To do this, modify the body of startBorrowItemActivity to be the following:

val intent = Intent(this, BorrowedItemActivity::class.java)
if (id != null) {
  intent.putExtra(INTENT_EXTRA_KEY, id)
}
startActivity(intent)

Here, it passes the selected entity’s id to the next BorrowedItemActivity.

Now the next Activity needs to read this id and populate the input field with the values of the Entity. To do this, first create a variable to store the entity to be edited, as follows inside BorrowedItemActivity:

private var borrowItemToBeEdited: BorrowedItemModel? = null

Now, add the following block inside onCreate() right below setContentView():

val borrowId = intent.extras?.getLong(MainActivity.INTENT_EXTRA_KEY)
if (borrowId != null) {
  borrowItemToBeEdited = borrowBox.get(borrowId)
  borrowed_item_name_edittext.setText(borrowItemToBeEdited?.itemName)
  borrower_name_edittext.setText(borrowItemToBeEdited?.borrowerName)
  borrow_date_textview.text= borrowItemToBeEdited?.borrowDate
}

borrowBox.get(borrowId) reads the entity id from the intent and then reads the correct entity from the database using the id. It then uses the item’s values and assigns them to the inputs.

There’s one step left. You need to update the existing entity and not create another entity in the Box. To do this, add the following block right before adding the entity to the box using borrowBox.put(borrowedItem):

if (borrowItemToBeEdited != null) {
  borrowedItem.id = borrowItemToBeEdited!!.id
}

This sets the entity’s id to the one passed to the Activity and thus, updates the entity.

Build and run the project. Click on any row in the list, update any field and click the FloatingActionButton. You’ll see the row was updated with the new values.

the row corresponding to your entity is edited