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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Saving Data with an ObjectBox Database on Android
25 mins
- When to Use a Local Database
- Types of Databases
- Choosing the Right Type of Database
- CRUD Operations
- Getting Started
- Integrating a Relational Database
- Adding ObjectBox to Your Project
- Creating the Database Entry Structure
- Creating the BoxStore
- Add Entities to the Database
- Reading From the Database
- Editing an Entity
- Deleting an Entity
- Sorting the Entities
- Searching for Entities
- Integrating a Document-Oriented Database
- Where to Go From Here?
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:
- First, the code verifies all the required fields.
- Then it creates a
BorrowedItemModel
instance with the entered values. - 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.
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.
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.